diveintopython-zh-5.4b/0000755000175000017500000000000010677542312016303 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/0000755000175000017500000000000010677542312016733 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/kgp/0000755000175000017500000000000010675463444017522 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/kgp/stderr.py0000644000175000017500000000015310663321430021357 0ustar freeflyingfreeflyingimport sys fsock = open('error.log', 'w') sys.stderr = fsock raise Exception, 'this error will be logged' diveintopython-zh-5.4b/py/kgp/kgp.dtd0000644000175000017500000000041010663321430020754 0ustar freeflyingfreeflying diveintopython-zh-5.4b/py/kgp/toolbox.py0000644000175000017500000000341010663321430021541 0ustar freeflyingfreeflying"""Miscellaneous utility functions This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" def openAnything(source): """URI, filename, or string --> stream This function lets you define parsers that take any input source (URL, pathname to local or network file, or actual data as a string) and deal with it in a uniform manner. Returned object is guaranteed to have all the basic stdio read methods (read, readline, readlines). Just .close() the object when you're done with it. Examples: >>> from xml.dom import minidom >>> sock = openAnything("http://localhost/kant.xml") >>> doc = minidom.parse(sock) >>> sock.close() >>> sock = openAnything("c:\\inetpub\\wwwroot\\kant.xml") >>> doc = minidom.parse(sock) >>> sock.close() >>> sock = openAnything("andor") >>> doc = minidom.parse(sock) >>> sock.close() """ if hasattr(source, "read"): return source if source == "-": import sys return sys.stdin # try to open with urllib (if source is http, ftp, or file URL) import urllib try: return urllib.urlopen(source) except (IOError, OSError): pass # try to open with native open function (if source is pathname) try: return open(source) except (IOError, OSError): pass # treat source as string import StringIO return StringIO.StringIO(str(source)) diveintopython-zh-5.4b/py/kgp/binary.xml0000644000175000017500000000052510663321430021513 0ustar freeflyingfreeflying

0

1

diveintopython-zh-5.4b/py/kgp/stdout.py0000644000175000017500000000027510663321430021403 0ustar freeflyingfreeflyingimport sys print 'Dive in' saveout = sys.stdout fsock = open('out.log', 'w') sys.stdout = fsock print 'This message will be logged instead of displayed' sys.stdout = saveout fsock.close() diveintopython-zh-5.4b/py/kgp/thanks.xml0000644000175000017500000004041210663321430021516 0ustar freeflyingfreeflying

new clothes

a really good book

drugs

comic books

booze for a party I'm throwing this weekend

new computer hardware

a stuffed animal

a cute little pewter castle with crystals on the towers

sexy underwear

a bread machine

car repairs

a digital watch

a new pet hamster

a new toaster

shampoo

things for my new baby

legal fees

my divorce

this month's rent

food

for the baby

for the next

week

few days

plastic surgery

I'm planning to take it to the shooting range the next time I go.

I'm sure I will put it to good use.

Everyone I konw is envious.

It looks lovely in my .

I've made it the central focus of my .

My looked empty without it.

Bob

Jim

John

Fred

Elmer

Charlie

Lester

David

Mark

Andrew

Pete

Bill

William

James

Richard

Scott

Nathan

Matt

Jeff

Archie

Tom

Harry

Vinnie

Michael

Dan

Ray

Roy

Todd

Chad

Jeremy

Jason

Kurt

Keith

Ken

Tim

Randall

Eric

Stuart

Roger

Alex

Joel

Don

Ron

Arnold

Frank

Ted

Gary

Josh

Warren

Nick

Ben

Calvin

Martin

Jake

Ed

$5

$10

$15

$20

$25

$30

$35

$40

$45

$50

$75

$100

Mary

Emily

Anne

Kathy

Natalie

Ellen

Joan

Jean

Jill

Rachel

Kendra

Sabina

Sheila

Jessica

Andrea

Megan

Alison

Robin

Lynn

Joy

Wendy

Kristin

Donna

Kim

Jen

Beth

Lisa

Angie

Sarah

Peggy

Becky

Laura

Nicole

Melanie

Miriam

Alicia

Sylvia

Clara

Julie

Rhoda

Rhonda

Greta

Amelia

Emma

Courtney

Ashley

Stephanie

Vicky

Lois

Thelma

Ruth

Elizabeth

Sandy

Stella

Carolyn

Maria

Marjorie

Edith

Teresa

Linda

Sue

Rose

April

Frances

Dora

living room

bathroom

basement

bedroom

closet

kitchen

garage

attic

dining room

hallway

guest room

sewing room

office

billiard parlor

junk drawer

backyard

doghouse

and

and

and

and

Maxim

The New Yorker

Time

Newsweek

Guns and Ammo

Esquire

GQ

Cosmopolitan

The American Spectator

The Nation

Mother Jones

Field and Stream

Reader's Digest

The Journal of the American Chemical Society

Mind

Discover

Games

MacWorld

New Republic

Wired

Grandma

Mom

Aunt

sister

Grandpa

Dad

Uncle

brother

dead

in prison

in a labor camp in Siberia

in the hospital

reported missing last month

broke

destitute

in the witness relocation program

I've already

put

stashed

it in

the bank

a shoebox

to save for

.

I'd love to spend it, but

I'm saving it to buy .

It's nice to have some "fun money" to spend, but

I've decided to save it for .

I'd love to spend it

immediately

right away

, but

I need to save up for .

Dear ,

It's not much by today's standards, but every little bit helps!

It was either that or give it to the poor.

This is

just a brief note to

say

thanks

"thank you"

thank you

for the

you sent

I received from you

for .

Of all the

presents

gifts

things

stuff

I

received

got

for , I

liked

loved

your

gift of

the most

more than anything else

.

I

really

appreciate

enjoyed receiving

the you

gave

sent

me for .

I

really

love

getting

receiving

money for ,

since

because

that

it

means I can

always

go out and

spend it on

use it for

what I really

want

need

.

Thanks

Thank you

for the .

You can't imagine how surprised I was to discover that you had sent me for .

Thanks

Thank you

for the

. I

; i

t was

the perfect

a great

present

gift

for .

I don't know how to thank you

properly

enough

for the you

sent

gave

me

for .

I'm

just

writing to say

thanks

"thank you"

for the you

graciously

gave

sent

me for .

Thank you

Thanks

for the you

bestowed upon

sent

me for .

This is

just a quick note to

say "thank you"

thank you

for the

I

got

received

from you

you sent

me

for .

This is

just a brief note to

say

thanks

"thank you"

thank you

for the

you sent

I received from you

for .

Of all the

presents

gifts

things

stuff

I

received

got

for , I

liked

loved

your

gift of

the most

more than anything else

.

I

really

appreciate

enjoyed receiving

the you

gave

sent

me for .

I

really

love

getting

receiving

money for ,

since

because

that

it

means I can

always

go out and

spend it on

use it for

what I really

want

need

.

Thanks

Thank you

for the .

You can't imagine how surprised I was to discover that you had sent me for .

Thanks

Thank you

for the

. I

; i

t was

the perfect

a great

present

gift

for .

I don't know how to thank you

properly

enough

for the you

sent

gave

me

for .

I'm

just

writing to say

thanks

"thank you"

for the you

graciously

gave

sent

me for .

Thank you

Thanks

for the you

bestowed upon

sent

me for .

This is

just a quick note to

say "thank you"

thank you

for the

I

got

received

from you

you sent

me

for .

Christmas

Valentine's Day

my birthday

Easter

New Year's

Hanukkah

our wedding

our divorce

my half-birthday

my confirmation

my Bar Mitzvah

my debutante ball

my coming-out party

our first baby

my bachelor party

my bridal shower

our housewarming party

I know how much of a sacrifice this sort of gift is for you.

and tried to steal it from me, but I was too quick for them.

I'm

looking forward to getting your next gift for .

Frankly,

it was

a little

strange to get anything from you

at all

, because

I thought

my friends to me that

you were .

How thoughtful of you.

Give my love to

.

Best wishes to you

and

.

Sincerely

Love

always

,

Thank you

again

,

See you soon,

Hugs and kisses,

From,

Thanks

again

,

Peace,

Faithfully,

You'll be happy to know that

I've already spent it on .

It

's

has

already

been well-spent on .

My

mother

father

insisted that I spend it on .

Now I

finally

have enough money for .

As soon as I can,

When I get a chance,

I'm going

to the mall

and spending it on .

To be honest,

I tried to get it to the bank

I wanted to save it

, but I

realized I

needed

had

to spend it on

instead

.

I just wanted to let you know that

it's already gone towards .

I

immediately

rushed right out and

spent it on

for the first time

in years

.

As soon as I finish writing this letter,

I'm going to put it towards .

I have to admit that

I already spent it on this month's protection.

toaster

blender

pajamas

wallet

umbrella

shampoo

mouthwash

beer

disk drive

mousepad

stereo

compact disc

dart board

bread machine

moustache comb

fruitcake

towel rack

bong

jigsaw puzzle

Star Trek "Picard" doll

stuffed animal

beanbag chair

box of chocolates

microwave oven

snowblower

jacket

sweatshirt

tie

laundry detergent

fake tree

makeup kit

miniature pool table

carton of cigarettes

basketball

fake vomit

book

subscription to

"Critique of Pure Reason"

diveintopython-zh-5.4b/py/kgp/kant.xml0000644000175000017500000003400410663321430021163 0ustar freeflyingfreeflying

and

but

yet

all of

some of

none of

general

applied

pure

transcendental

formal

universal

necessary

practical

contradictory

sufficient

hypothetical

problematic

analytic

synthetic

ampliative

inductive

speculative

disjunctive

a priori

a posteriori

pure

practical

human

natural

intelligible

transcendental

empirical

Aristotle

Hume

Galileo

the transcendental aesthetic

logic

the Ideal of reason

the architectonic of reason

the discipline of reason

the

pure

practical

employment of

the Ideal

the manifold

the Transcendental Deduction

our experience

philosophy

metaphysics

the thing in itself

our understanding

our

knowledge

reason

space

time

the transcendental unity of apperception

necessity

the never-ending regress in the series of empirical conditions

the Antinomies

the paralogisms

of reason

the Categories

our sense perceptions

our faculties

our

judgements

the objects in space and time

the things in themselves

natural causes

our ideas

our

concepts

the

objects in space and time

the noumena

the phenomena

is what first gives rise to

can thereby determine in its totality

has lying before it

constitutes the whole content for

may not contradict itself, but it is still possible that it may be in contradictions with

would thereby be made to contradict

teaches us nothing whatsoever regarding the content of

can not take account of

has nothing to do with

stands in need of

is the key to understanding

proves the validity of

is just as necessary as

is the clue to the discovery of

is a representation of

depends on

excludes the possibility of

is the mere result of the power of , a blind but indispensable function of the soul

occupies part of the sphere of concerning the existence of in general

is by its very nature contradictory

would be falsified

abstracts from all content of

knowledge

is a body of demonstrated science, and it must be known

can never furnish a true and demonstrated science, because, like , it principles

can be treated like

exists in

are what first give rise to

have lying before them

constitute the whole content of

would thereby be made to contradict

can not take account of

have nothing to do with

stand in need to

are the clue to the discovery of

prove the validity of

are just as necessary as

are a representation of

exclude the possibility of

are the mere results of the power of , a blind but indispensable function of the soul

occupy part of the sphere of concerning the existence of in general

are by their very nature contradictory

would be falsified

abstract from all content of

knowledge

constitute a body of demonstrated doctrine, and this body must be known

can never, as a whole, furnish a true and demonstrated science, because, like , they principles

can be treated like

should only be used as a canon for

exist in

in all theoretical sciences

in view of these considerations

thus

by means of

in the study of

therefore

with the sole exception of

certainly

still

as I have elsewhere shown

on the other hand

for these reasons

in the case of

however

in natural theology

consequently

it must not be supposed that

there can be no doubt that

we can deduce that

it is not at all certain that

tells us that

it remains a mystery why

I assert

, ,

that

to avoid all misapprehension, it is necessary to explain that

let us suppose that

it is obvious that

the reader should be careful to observe that

what we have alone been able to show is that

because of our necessary ignorance of the conditions

as is shown in the writings of

as is proven in the ontological manuals

as any dedicated reader can clearly see

as is evident upon close examination

as will easily be shown in the next section

since knowledge of is

by virtue of reason

as we have already seen

since are

because of the relation between and

by means of analysis

by means of analytic unity

in so far as this expounds the rules of

when thus treated as

in other words

in the full sense of these terms

insomuch as relies on

indeed

then

that is to say

even as this relates to

in respect of the intelligible character

so regarded

for example

irrespective of all empirical conditions

so far as regards

and

on the contrary

in accordance with the principles of

in reference to ends

in particular

so far as I know

(and this is true)

, ,

,

,

,

,

(and this is the case)

, ,

,

,

,

,

,

,

.

,

, ,

,

.

,

; ,

.

Whence comes , the solution of which involves the relation between

and

?

,

is it

true

the case

that

, or is the real question whether ?

Has it ever been suggested that

, ,

there is

no relation

a causal connection

bewteen

and

?

In which of our cognitive faculties are

and

connected together?

can I entertain in thought, or does it present itself to me?

But we have fallen short of the necessary interconnection that we have in mind when we speak of

.

We thus have a pure synthesis of apprehension.

And similarly with all the others.

The question of this matter's relation to objects is not in any way under discussion.

This distinction must have some ground in the nature of

.

The divisions are thus provided; all that is required is to fill them.

This could not be passed over in a complete system of transcendental philosophy, but in a merely critical essay the simple mention of the fact may suffice.

This is not something we are in a position to establish.

This is the sense in which it is to be understood in this work.

But this need not worry us.

Let us apply this to .

But to this matter no answer is possible.

But the proof of this is a task from which we can here be absolved.

But at present we shall turn our attention to .

This may be clear with an example.

I feel I have sufficiently shown this to be true.

This is what chiefly concerns us.

On this matter, what has been said already should in any case suffice by itself.

In my present remarks I am referring to only in so far as it is founded on principles.

But this is to be dismissed as random groping.

()

diveintopython-zh-5.4b/py/kgp/husserl.xml0000644000175000017500000002430610663321430021717 0ustar freeflyingfreeflying

the phenomenon

an object

the cogitatum

(qua cogitatum)

transcendental

phenomenology

pure

and genuine

scientific

evidence

cognition

the ego cogito

transcendental subjectivity

the transcendental-phenomenological reduction

the

phenomenological

epoche

the Objective world

a transcendental grounding of

philosophy

the stream of

what is itself given

the repeatable act of grounding

of

an infinite horizon of approximations

the Ego

the fundamental form of this universal synthesis

the

all-embracing

consciousness of internal time

immanent time

the task of clarifying

the whole of conscious life

noetic acts

cogitationes

noematic descriptions

separated

modes of consciousness

multiplicities of

experiences

denotes a universal primal phenomenon of

is only a modality of

becomes modalized also in correlation with

stands in contrast to the accidental being "for me" of

is a clarification of the striving for

becomes adjusted to

exist for us thanks to

denote the universal primary phenomena of

are only modalities of

become modalized also in correlation with

stand in contrast to

the accident being "for me" of

become adjusted to

inhibits acceptance of as existent

is actual

does not yet produce for us any abiding being

is "in itself"

is an infinite idea, related to infinities of harmoniously combinable

is an agreement of with the judged

can be seen as full proof that, in spite of the continual experiencedness of , a non-being of is conceivable

needs to be criticized with regard to its validity and range, before it can be used for the purposes of a radical grounding of

is precisely what makes critical decisions about at all possible

is unified synthetically

synthetically constitutes all particular that ever become prominent

inhibit

my

our

acceptance of

as existent

do not yet produce for

us

me

any abiding being

apart from their relation to

are "in themselves"

are infinite ideas, related to infinities of harmoniously combinable

and

can be seen as

full

proof that, in spite of the continual experiencedness of , a non-being of

is

conceivable

possible

need to be criticized with regard to their validity and range, before they can be used for

the purposes of

a radical grounding of

are precisely what make critical decisions about

at all possible

are unified synthetically

synthetically constitute all particular instances of that ever become prominent

in the natural attitude

de facto

owing to the instability and ambiguity of

by immersing ourselves in such a striving

in other words

by this preliminary work, here roughly indicated rather than done explicitly

where this is still wanting

since the form belonging to a systematic order of

is part of this idea

in the broadest sense

as we have said

in the attitude established by transcendental reduction

in a maximally broad sense

if we maintain this attitude

in the broadest Cartesian sense

it is plain that

by immersing ourselves meditatively in the general intentions of

, we discover that

if we follow up this doubt, it becomes manifest that

by virtue of my free epoche with respect to the being of the experienced world, the momentous fact is that

yet it must not be overlooked that

the fact is that

we can be sure that

hence it follows without more ado that

calls

call

our attention to the fact that

we see in advance that

the fact is evident

, even apodictically evident,

that

it becomes evident that

in an extremely broad sense

consequently

in respect of this evidence

however

mediately

naturally

even with respect to the evidence in which

presents itself

present themselves

as a matter of essential necessity

perchance

when we let our thoughts hasten in this manner

by conscious conversion into the corresponding

by virture of a synthesis in which what is meant coincides and agree with

by a freely actualizable return to

by reconciling with

by orienting

according to accured insights

by the fundamental nature of

, ,

;

()

, ,

, ,

()

,

;

reflecting

phenomenological

transcendental

worldly

I

we

now shift the weight of transcendental evidence of

()

from the

ego to

we must not let ourselves be frightened by considerations of and

only in reflection do we "direct" ourselves to and to its perceptual directedness to

we have not simply lost for phenomenology; we retain it

, ,

I have the reflection that is given continuously as an objective unity in a multi-form and changeable multiplicity of , which belong determinately to it

I

, the meditating phenomenologist,

set myself the all-embracing task of uncovering

myself

.

.

, ,

.

diveintopython-zh-5.4b/py/kgp/test.xml0000644000175000017500000000071410663321430021206 0ustar freeflyingfreeflying

0

1

1

2

3

1

1

diveintopython-zh-5.4b/py/kgp/russiansample.xml0000644000175000017500000000013010663321430023105 0ustar freeflyingfreeflying diveintopython-zh-5.4b/py/kgp/kgp.py0000644000175000017500000002105010663321430020634 0ustar freeflyingfreeflying#!/usr/bin/env python2 """Kant Generator for Python Generates mock philosophy based on a context-free grammar Usage: python kgp.py [options] [source] Options: -g ..., --grammar=... use specified grammar file or URL -h, --help show this help -d show debugging information while parsing Examples: kgp.py generates several paragraphs of Kantian philosophy kgp.py -g husserl.xml generates several paragraphs of Husserl kpg.py "" generates a paragraph of Kant kgp.py template.xml reads from template.xml to decide what to generate This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.4 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" from xml.dom import minidom import random import toolbox import sys import getopt _debug = 0 class NoSourceError(Exception): pass class KantGenerator: """generates mock philosophy based on a context-free grammar""" def __init__(self, grammar, source=None): self.loadGrammar(grammar) self.loadSource(source and source or self.getDefaultSource()) self.refresh() def _load(self, source): """load XML input source, return parsed XML document - a URL of a remote XML file ("http://diveintopython.org/kant.xml") - a filename of a local XML file ("~/diveintopython/common/py/kant.xml") - standard input ("-") - the actual XML document, as a string """ sock = toolbox.openAnything(source) xmldoc = minidom.parse(sock).documentElement sock.close() return xmldoc def loadGrammar(self, grammar): """load context-free grammar""" self.grammar = self._load(grammar) self.refs = {} for ref in self.grammar.getElementsByTagName("ref"): self.refs[ref.attributes["id"].value] = ref def loadSource(self, source): """load source""" self.source = self._load(source) def getDefaultSource(self): """guess default source of the current grammar The default source will be one of the s that is not cross-referenced. This sounds complicated but it's not. Example: The default source for kant.xml is "", because 'section' is the one that is not 'd anywhere in the grammar. In most grammars, the default source will produce the longest (and most interesting) output. """ xrefs = {} for xref in self.grammar.getElementsByTagName("xref"): xrefs[xref.attributes["id"].value] = 1 xrefs = xrefs.keys() standaloneXrefs = [e for e in self.refs.keys() if e not in xrefs] if not standaloneXrefs: raise NoSourceError, "can't guess source, and no source specified" return '' % random.choice(standaloneXrefs) def reset(self): """reset parser""" self.pieces = [] self.capitalizeNextWord = 0 def refresh(self): """reset output buffer, re-parse entire source file, and return output Since parsing involves a good deal of randomness, this is an easy way to get new output without having to reload a grammar file each time. """ self.reset() self.parse(self.source) return self.output() def output(self): """output generated text""" return "".join(self.pieces) def randomChildElement(self, node): """choose a random child element of a node This is a utility method used by do_xref and do_choice. """ choices = [e for e in node.childNodes if e.nodeType == e.ELEMENT_NODE] chosen = random.choice(choices) if _debug: sys.stderr.write('%s available choices: %s\n' % \ (len(choices), [e.toxml() for e in choices])) sys.stderr.write('Chosen: %s\n' % chosen.toxml()) return chosen def parse(self, node): """parse a single XML node A parsed XML document (from minidom.parse) is a tree of nodes of various types. Each node is represented by an instance of the corresponding Python class (Element for a tag, Text for text data, Document for the top-level document). The following statement constructs the name of a class method based on the type of node we're parsing ("parse_Element" for an Element node, "parse_Text" for a Text node, etc.) and then calls the method. """ parseMethod = getattr(self, "parse_%s" % node.__class__.__name__) parseMethod(node) def parse_Document(self, node): """parse the document node The document node by itself isn't interesting (to us), but its only child, node.documentElement, is: it's the root node of the grammar. """ self.parse(node.documentElement) def parse_Text(self, node): """parse a text node The text of a text node is usually added to the output buffer verbatim. The one exception is that

sets a flag to capitalize the first letter of the next word. If that flag is set, we capitalize the text and reset the flag. """ text = node.data if self.capitalizeNextWord: self.pieces.append(text[0].upper()) self.pieces.append(text[1:]) self.capitalizeNextWord = 0 else: self.pieces.append(text) def parse_Element(self, node): """parse an element An XML element corresponds to an actual tag in the source: ,

, , etc. Each element type is handled in its own method. Like we did in parse(), we construct a method name based on the name of the element ("do_xref" for an tag, etc.) and call the method. """ handlerMethod = getattr(self, "do_%s" % node.tagName) handlerMethod(node) def parse_Comment(self, node): """parse a comment The grammar can contain XML comments, but we ignore them """ pass def do_xref(self, node): """handle tag An tag is a cross-reference to a tag. evaluates to a randomly chosen child of . """ id = node.attributes["id"].value self.parse(self.randomChildElement(self.refs[id])) def do_p(self, node): """handle

tag The

tag is the core of the grammar. It can contain almost anything: freeform text, tags, tags, even other

tags. If a "class='sentence'" attribute is found, a flag is set and the next word will be capitalized. If a "chance='X'" attribute is found, there is an X% chance that the tag will be evaluated (and therefore a (100-X)% chance that it will be completely ignored) """ keys = node.attributes.keys() if "class" in keys: if node.attributes["class"].value == "sentence": self.capitalizeNextWord = 1 if "chance" in keys: chance = int(node.attributes["chance"].value) doit = (chance > random.randrange(100)) else: doit = 1 if doit: for child in node.childNodes: self.parse(child) def do_choice(self, node): """handle tag A tag contains one or more

tags. One

tag is chosen at random and evaluated; the rest are ignored. """ self.parse(self.randomChildElement(node)) def usage(): print __doc__ def main(argv): grammar = "kant.xml" try: opts, args = getopt.getopt(argv, "hg:d", ["help", "grammar="]) except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): usage() sys.exit() elif opt == '-d': global _debug _debug = 1 elif opt in ("-g", "--grammar"): grammar = arg source = "".join(args) k = KantGenerator(grammar, source) print k.output() if __name__ == "__main__": main(sys.argv[1:]) diveintopython-zh-5.4b/py/kgp/template.xml0000644000175000017500000000002610663321430022036 0ustar freeflyingfreeflying diveintopython-zh-5.4b/py/romantest.py0000644000175000017500000001067110663321430021315 0ustar freeflyingfreeflying"""Unit test for roman.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman.OutOfRangeError, roman.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman.OutOfRangeError, roman.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman.OutOfRangeError, roman.toRoman, -1) def testDecimal(self): """toRoman should fail with non-integer input""" self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman.toRoman(integer) result = roman.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman.toRoman(integer) roman.fromRoman(numeral.upper()) self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/apihelpertest.py0000644000175000017500000000354310663321430022152 0ustar freeflyingfreeflying"""Unit test for apihelper.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.4 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import unittest import apihelper import sys from StringIO import StringIO class Redirector(unittest.TestCase): def setUp(self): self.savestdout = sys.stdout self.redirect = StringIO() sys.stdout = self.redirect def tearDown(self): sys.stdout = self.savestdout class KnownValues(Redirector): def testApiHelper(self): """info should return known result for apihelper""" apihelper.info(apihelper) self.redirect.seek(0) self.assertEqual(self.redirect.read(), """info Print methods and doc strings. Takes module, class, list, dictionary, or string. """) class ParamChecks(Redirector): def testSpacing(self): """info should honor spacing argument""" apihelper.info(apihelper, spacing=20) self.redirect.seek(0) self.assertEqual(self.redirect.read(), """info Print methods and doc strings. Takes module, class, list, dictionary, or string. """) def testCollapse(self): """info should honor collapse argument""" apihelper.info(apihelper, collapse=0) self.redirect.seek(0) self.assertEqual(self.redirect.read(), """info Print methods and doc strings. Takes module, class, list, dictionary, or string. """) class BadInput(unittest.TestCase): def testNoObject(self): """info should fail with no object""" self.assertRaises(TypeError, apihelper.info, spacing=20) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/BaseHTMLProcessor.py0000644000175000017500000000724610663321430022544 0ustar freeflyingfreeflying"""Base class for creating HTML processing modules This class is designed to take HTML as input and spit out equivalent HTML as output. By itself it's not very interesting; you use it by subclassing it and providing the methods you need to create your HTML transformation. This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" from sgmllib import SGMLParser import htmlentitydefs class BaseHTMLProcessor(SGMLParser): def reset(self): # extend (called by SGMLParser.__init__) self.pieces = [] SGMLParser.reset(self) def unknown_starttag(self, tag, attrs): # called for each start tag # attrs is a list of (attr, value) tuples # e.g. for

, tag="pre", attrs=[("class", "screen")]
		# Ideally we would like to reconstruct original tag and attributes, but
		# we may end up quoting attribute values that weren't quoted in the source
		# document, or we may change the type of quotes around the attribute value
		# (single to double quotes).
		# Note that improperly embedded non-HTML code (like client-side Javascript)
		# may be parsed incorrectly by the ancestor, causing runtime script errors.
		# All non-HTML code must be enclosed in HTML comment tags ()
		# to ensure that it will pass through this parser unaltered (in handle_comment).
		strattrs = "".join([' %s="%s"' % (key, value) for key, value in attrs])
		self.pieces.append("<%(tag)s%(strattrs)s>" % locals())
		
	def unknown_endtag(self, tag):
		# called for each end tag, e.g. for 
, tag will be "pre" # Reconstruct the original end tag. self.pieces.append("" % locals()) def handle_charref(self, ref): # called for each character reference, e.g. for " ", ref will be "160" # Reconstruct the original character reference. self.pieces.append("&#%(ref)s;" % locals()) def handle_entityref(self, ref): # called for each entity reference, e.g. for "©", ref will be "copy" # Reconstruct the original entity reference. self.pieces.append("&%(ref)s" % locals()) # standard HTML entities are closed with a semicolon; other entities are not if htmlentitydefs.entitydefs.has_key(ref): self.pieces.append(";") def handle_data(self, text): # called for each block of plain text, i.e. outside of any tag and # not containing any character or entity references # Store the original text verbatim. self.pieces.append(text) def handle_comment(self, text): # called for each HTML comment, e.g. # Reconstruct the original comment. # It is especially important that the source document enclose client-side # code (like Javascript) within comments so it can pass through this # processor undisturbed; see comments in unknown_starttag for details. self.pieces.append("" % locals()) def handle_pi(self, text): # called for each processing instruction, e.g. # Reconstruct original processing instruction. self.pieces.append("" % locals()) def handle_decl(self, text): # called for the DOCTYPE, if present, e.g. # # Reconstruct original DOCTYPE self.pieces.append("" % locals()) def output(self): """Return processed HTML as a single string""" return "".join(self.pieces) if __name__ == "__main__": for k, v in globals().items(): print k, "=", v diveintopython-zh-5.4b/py/plural.py0000644000175000017500000000176610663321430020605 0ustar freeflyingfreeflying"""Pluralize English nouns (stage 6) This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. Command line usage: $ python plural6.py noun nouns """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.7 $" __date__ = "$Date: 2004/05/03 19:40:42 $" __copyright__ = "Copyright (c) 2004 Mark Pilgrim" __license__ = "Python" import re def rules(language): for line in file('plural-rules.%s' % language): pattern, search, replace = line.split() yield lambda word: re.search(pattern, word) and re.sub(search, replace, word) def plural(noun, language='en'): """returns the plural form of a noun""" for applyRule in rules(language): result = applyRule(noun) if result: return result if __name__ == '__main__': import sys if sys.argv[1:]: print plural(sys.argv[1]) else: print __doc__ diveintopython-zh-5.4b/py/autosize.py0000644000175000017500000000545510663321430021150 0ustar freeflyingfreeflying""" Add size of all downloadable archives as title attribute of download link This script is used during the build process of "Dive Into Python" (http://diveintopython.org/) to add size descriptions to all download links on the home page. Requires that the links be relative paths from the current working directory. Also requires that the download links already have some title already; download size is appended to the existing title. Looks for two arguments on the command line. First: if a file, the file is processed. If a directory, all .html files in the directory are processed. Second: directory of files to use for sizing information. If no arguments given, a test suite is performed on a hard-coded test file which saves the output to a temporary file and opens it in a web browser locally. Not safe to run on the same file(s) more than once, since the size information is simply concatenated to the existing title. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import sys import os import stat import urlparse from BaseHTMLProcessor import BaseHTMLProcessor class AutosizeParser(BaseHTMLProcessor): def __init__(self, basedir): BaseHTMLProcessor.__init__(self) self.basedir = basedir def start_a(self, attrs): try: href = [e[1] for e in attrs if e[0]=='href'][0] title = [e[1] for e in attrs if e[0]=='title'][0] except IndexError: pass else: filename = os.path.split(urlparse.urlparse(href)[2])[1] if os.path.splitext(filename)[1] in ('.zip', '.tgz', '.hqx'): zipfile = os.path.join(self.basedir, filename) title += " (%d KB)" % ((os.stat(zipfile)[stat.ST_SIZE] + 1023)/1024,) attrs = tuple([e for e in attrs if e[0]<>'title'] + [('title', title)]) self.unknown_starttag("a", attrs) def process(filename, basedir, outfile=None): if not outfile: outfile = filename sock = open(filename, "r") parser = AutosizeParser(basedir) parser.feed(sock.read()) output = parser.output() sock.close() sock = open(outfile, "w") sock.write(output) sock.close() return output def test(filename, basedir, outfile="c:\\out.html"): output = process(filename, basedir, outfile) print output import webbrowser webbrowser.open(outfile) if __name__ == "__main__": if sys.argv[1:]: filedir = sys.argv[1] basedir = sys.argv[2] if os.path.isdir(filedir): for f in [os.path.join(filedir, s) for s in os.listdir(filedir) if os.path.splitext(s)[1].lower() == '.html']: ## print "Autosizing %s" % os.path.basename(f) process(f, basedir) else: ## print "Autosizing %s" % os.path.basename(filedir) process(filedir, basedir) else: test("c:\\docbook\\dip\\dist\\html\\index.html", "c:\\docbook\\dip\\dist\\download\\") diveintopython-zh-5.4b/py/roman/0000755000175000017500000000000010663321426020043 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage1/0000755000175000017500000000000010663321426021227 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage1/romantest1.py0000644000175000017500000001257010663321426023703 0ustar freeflyingfreeflying"""Unit test for roman1.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman1 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman1.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman1.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman1.NotIntegerError, roman1.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s) class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman1.toRoman(integer) result = roman1.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman1.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman1.toRoman(integer) roman1.fromRoman(numeral.upper()) self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage1/roman1.py0000644000175000017500000000131710663321426023000 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass def toRoman(n): """convert integer to Roman numeral""" pass def fromRoman(s): """convert Roman numeral to integer""" pass diveintopython-zh-5.4b/py/roman/stage2/0000755000175000017500000000000010663321426021230 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage2/romantest2.py0000644000175000017500000001257010663321426023705 0ustar freeflyingfreeflying"""Unit test for roman2.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman2 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman2.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman2.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman2.OutOfRangeError, roman2.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman2.OutOfRangeError, roman2.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman2.OutOfRangeError, roman2.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman2.NotIntegerError, roman2.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman2.InvalidRomanNumeralError, roman2.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman2.InvalidRomanNumeralError, roman2.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman2.InvalidRomanNumeralError, roman2.fromRoman, s) class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman2.toRoman(integer) result = roman2.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman2.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman2.toRoman(integer) roman2.fromRoman(numeral.upper()) self.assertRaises(roman2.InvalidRomanNumeralError, roman2.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage2/roman2.py0000644000175000017500000000242410663321426023002 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result def fromRoman(s): """convert Roman numeral to integer""" pass diveintopython-zh-5.4b/py/roman/stage3/0000755000175000017500000000000010663321426021231 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage3/romantest3.py0000644000175000017500000001257010663321426023707 0ustar freeflyingfreeflying"""Unit test for roman3.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman3 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman3.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman3.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman3.OutOfRangeError, roman3.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman3.OutOfRangeError, roman3.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman3.OutOfRangeError, roman3.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman3.NotIntegerError, roman3.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman3.InvalidRomanNumeralError, roman3.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman3.InvalidRomanNumeralError, roman3.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman3.InvalidRomanNumeralError, roman3.fromRoman, s) class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman3.toRoman(integer) result = roman3.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman3.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman3.toRoman(integer) roman3.fromRoman(numeral.upper()) self.assertRaises(roman3.InvalidRomanNumeralError, roman3.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage3/roman3.py0000644000175000017500000000271610663321426023010 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 4000): raise OutOfRangeError, "number out of range (must be 1..3999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result def fromRoman(s): """convert Roman numeral to integer""" pass diveintopython-zh-5.4b/py/roman/stage4/0000755000175000017500000000000010663321426021232 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage4/romantest4.py0000644000175000017500000001257010663321426023711 0ustar freeflyingfreeflying"""Unit test for roman4.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman4 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman4.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman4.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman4.OutOfRangeError, roman4.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman4.OutOfRangeError, roman4.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman4.OutOfRangeError, roman4.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman4.NotIntegerError, roman4.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, s) class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman4.toRoman(integer) result = roman4.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman4.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman4.toRoman(integer) roman4.fromRoman(numeral.upper()) self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage4/roman4.py0000644000175000017500000000322710663321426023010 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 4000): raise OutOfRangeError, "number out of range (must be 1..3999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result def fromRoman(s): """convert Roman numeral to integer""" result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage5/0000755000175000017500000000000010663321426021233 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage5/romantest5.py0000644000175000017500000001257010663321426023713 0ustar freeflyingfreeflying"""Unit test for roman5.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman5 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman5.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman5.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman5.OutOfRangeError, roman5.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman5.OutOfRangeError, roman5.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman5.OutOfRangeError, roman5.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman5.NotIntegerError, roman5.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman5.InvalidRomanNumeralError, roman5.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman5.InvalidRomanNumeralError, roman5.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman5.InvalidRomanNumeralError, roman5.fromRoman, s) class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman5.toRoman(integer) result = roman5.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman5.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman5.toRoman(integer) roman5.fromRoman(numeral.upper()) self.assertRaises(roman5.InvalidRomanNumeralError, roman5.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage5/roman5.py0000644000175000017500000000363210663321426023012 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 4000): raise OutOfRangeError, "number out of range (must be 1..3999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' def fromRoman(s): """convert Roman numeral to integer""" if not re.search(romanNumeralPattern, s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage6/0000755000175000017500000000000010663321426021234 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage6/romantest61.py0000644000175000017500000001306410663321426023775 0ustar freeflyingfreeflying"""Unit test for roman61.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman61 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman61.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman61.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman61.OutOfRangeError, roman61.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman61.OutOfRangeError, roman61.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman61.OutOfRangeError, roman61.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman61.NotIntegerError, roman61.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman61.toRoman(integer) result = roman61.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman61.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman61.toRoman(integer) roman61.fromRoman(numeral.upper()) self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage6/romantest62.py0000644000175000017500000001306410663321426023776 0ustar freeflyingfreeflying"""Unit test for roman62.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman62 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman62.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman62.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman62.OutOfRangeError, roman62.toRoman, 4000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman62.OutOfRangeError, roman62.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman62.OutOfRangeError, roman62.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman62.NotIntegerError, roman62.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman62.InvalidRomanNumeralError, roman62.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman62.InvalidRomanNumeralError, roman62.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman62.InvalidRomanNumeralError, roman62.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman62.InvalidRomanNumeralError, roman62.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 4000): numeral = roman62.toRoman(integer) result = roman62.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 4000): numeral = roman62.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 4000): numeral = roman62.toRoman(integer) roman62.fromRoman(numeral.upper()) self.assertRaises(roman62.InvalidRomanNumeralError, roman62.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage6/roman61.py0000644000175000017500000000363210663321426023075 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 4000): raise OutOfRangeError, "number out of range (must be 1..3999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' def fromRoman(s): """convert Roman numeral to integer""" if not re.search(romanNumeralPattern, s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage6/roman62.py0000644000175000017500000000375110663321426023100 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 4000): raise OutOfRangeError, "number out of range (must be 1..3999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not re.search(romanNumeralPattern, s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage7/0000755000175000017500000000000010663321426021235 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage7/romantest71.py0000644000175000017500000001333010663321426023773 0ustar freeflyingfreeflying"""Unit test for roman71.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman71 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman71.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman71.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman71.NotIntegerError, roman71.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman71.toRoman(integer) result = roman71.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman71.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman71.toRoman(integer) roman71.fromRoman(numeral.upper()) self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage7/romantest72.py0000644000175000017500000001333010663321426023774 0ustar freeflyingfreeflying"""Unit test for roman72.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman72 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman72.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman72.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman72.OutOfRangeError, roman72.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman72.OutOfRangeError, roman72.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman72.OutOfRangeError, roman72.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman72.NotIntegerError, roman72.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman72.InvalidRomanNumeralError, roman72.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman72.InvalidRomanNumeralError, roman72.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman72.InvalidRomanNumeralError, roman72.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman72.InvalidRomanNumeralError, roman72.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman72.toRoman(integer) result = roman72.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman72.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman72.toRoman(integer) roman72.fromRoman(numeral.upper()) self.assertRaises(roman72.InvalidRomanNumeralError, roman72.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage7/roman71.py0000644000175000017500000000375110663321426023101 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 4000): raise OutOfRangeError, "number out of range (must be 1..3999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not re.search(romanNumeralPattern, s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage7/roman72.py0000644000175000017500000000375310663321426023104 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 5000): raise OutOfRangeError, "number out of range (must be 1..4999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = '^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not re.search(romanNumeralPattern, s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage8/0000755000175000017500000000000010663321426021236 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage8/romantest81.py0000644000175000017500000001333010663321426023775 0ustar freeflyingfreeflying"""Unit test for roman81.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman81 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman81.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman81.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman81.OutOfRangeError, roman81.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman81.OutOfRangeError, roman81.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman81.OutOfRangeError, roman81.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman81.NotIntegerError, roman81.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman81.InvalidRomanNumeralError, roman81.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman81.InvalidRomanNumeralError, roman81.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman81.InvalidRomanNumeralError, roman81.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman81.InvalidRomanNumeralError, roman81.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman81.toRoman(integer) result = roman81.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman81.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman81.toRoman(integer) roman81.fromRoman(numeral.upper()) self.assertRaises(roman81.InvalidRomanNumeralError, roman81.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage8/romantest82.py0000644000175000017500000001333010663321426023776 0ustar freeflyingfreeflying"""Unit test for roman82.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman82 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman82.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman82.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman82.OutOfRangeError, roman82.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman82.OutOfRangeError, roman82.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman82.OutOfRangeError, roman82.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman82.NotIntegerError, roman82.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman82.InvalidRomanNumeralError, roman82.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman82.InvalidRomanNumeralError, roman82.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman82.InvalidRomanNumeralError, roman82.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman82.InvalidRomanNumeralError, roman82.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman82.toRoman(integer) result = roman82.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman82.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman82.toRoman(integer) roman82.fromRoman(numeral.upper()) self.assertRaises(roman82.InvalidRomanNumeralError, roman82.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage8/romantest83.py0000644000175000017500000001333010663321426023777 0ustar freeflyingfreeflying"""Unit test for roman83.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman83 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman83.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman83.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman83.OutOfRangeError, roman83.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman83.OutOfRangeError, roman83.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman83.OutOfRangeError, roman83.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman83.NotIntegerError, roman83.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman83.InvalidRomanNumeralError, roman83.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman83.InvalidRomanNumeralError, roman83.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman83.InvalidRomanNumeralError, roman83.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman83.InvalidRomanNumeralError, roman83.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman83.toRoman(integer) result = roman83.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman83.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman83.toRoman(integer) roman83.fromRoman(numeral.upper()) self.assertRaises(roman83.InvalidRomanNumeralError, roman83.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage8/roman81.py0000644000175000017500000000377110663321426023105 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 5000): raise OutOfRangeError, "number out of range (must be 1..4999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = \ re.compile('^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$') def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not romanNumeralPattern.search(s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage8/roman82.py0000644000175000017500000000376710663321426023113 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 5000): raise OutOfRangeError, "number out of range (must be 1..4999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = \ re.compile('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$') def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not romanNumeralPattern.search(s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage8/roman83.py0000644000175000017500000000500110663321426023073 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 5000): raise OutOfRangeError, "number out of range (must be 1..4999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" result = "" for numeral, integer in romanNumeralMap: while n >= integer: result += numeral n -= integer return result #Define pattern to detect valid Roman numerals romanNumeralPattern = re.compile(''' ^ # beginning of string M{0,4} # thousands - 0 to 4 M's (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's), # or 500-800 (D, followed by 0 to 3 C's) (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's), # or 50-80 (L, followed by 0 to 3 X's) (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's), # or 5-8 (V, followed by 0 to 3 I's) $ # end of string ''' ,re.VERBOSE) def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not romanNumeralPattern.search(s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s result = 0 index = 0 for numeral, integer in romanNumeralMap: while s[index:index+len(numeral)] == numeral: result += integer index += len(numeral) return result diveintopython-zh-5.4b/py/roman/stage9/0000755000175000017500000000000010663321426021237 5ustar freeflyingfreeflyingdiveintopython-zh-5.4b/py/roman/stage9/romantest9.py0000644000175000017500000001327510663321426023726 0ustar freeflyingfreeflying"""Unit test for roman9.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import roman9 import unittest class KnownValues(unittest.TestCase): knownValues = ( (1, 'I'), (2, 'II'), (3, 'III'), (4, 'IV'), (5, 'V'), (6, 'VI'), (7, 'VII'), (8, 'VIII'), (9, 'IX'), (10, 'X'), (50, 'L'), (100, 'C'), (500, 'D'), (1000, 'M'), (31, 'XXXI'), (148, 'CXLVIII'), (294, 'CCXCIV'), (312, 'CCCXII'), (421, 'CDXXI'), (528, 'DXXVIII'), (621, 'DCXXI'), (782, 'DCCLXXXII'), (870, 'DCCCLXX'), (941, 'CMXLI'), (1043, 'MXLIII'), (1110, 'MCX'), (1226, 'MCCXXVI'), (1301, 'MCCCI'), (1485, 'MCDLXXXV'), (1509, 'MDIX'), (1607, 'MDCVII'), (1754, 'MDCCLIV'), (1832, 'MDCCCXXXII'), (1993, 'MCMXCIII'), (2074, 'MMLXXIV'), (2152, 'MMCLII'), (2212, 'MMCCXII'), (2343, 'MMCCCXLIII'), (2499, 'MMCDXCIX'), (2574, 'MMDLXXIV'), (2646, 'MMDCXLVI'), (2723, 'MMDCCXXIII'), (2892, 'MMDCCCXCII'), (2975, 'MMCMLXXV'), (3051, 'MMMLI'), (3185, 'MMMCLXXXV'), (3250, 'MMMCCL'), (3313, 'MMMCCCXIII'), (3408, 'MMMCDVIII'), (3501, 'MMMDI'), (3610, 'MMMDCX'), (3743, 'MMMDCCXLIII'), (3844, 'MMMDCCCXLIV'), (3888, 'MMMDCCCLXXXVIII'), (3940, 'MMMCMXL'), (3999, 'MMMCMXCIX'), (4000, 'MMMM'), (4500, 'MMMMD'), (4888, 'MMMMDCCCLXXXVIII'), (4999, 'MMMMCMXCIX')) def testToRomanKnownValues(self): """toRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman9.toRoman(integer) self.assertEqual(numeral, result) def testFromRomanKnownValues(self): """fromRoman should give known result with known input""" for integer, numeral in self.knownValues: result = roman9.fromRoman(numeral) self.assertEqual(integer, result) class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman9.OutOfRangeError, roman9.toRoman, 5000) def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman9.OutOfRangeError, roman9.toRoman, 0) def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman9.OutOfRangeError, roman9.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman9.NotIntegerError, roman9.toRoman, 0.5) class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman9.InvalidRomanNumeralError, roman9.fromRoman, s) def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman9.InvalidRomanNumeralError, roman9.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman9.InvalidRomanNumeralError, roman9.fromRoman, s) def testBlank(self): """fromRoman should fail with blank string""" self.assertRaises(roman9.InvalidRomanNumeralError, roman9.fromRoman, "") class SanityCheck(unittest.TestCase): def testSanity(self): """fromRoman(toRoman(n))==n for all n""" for integer in range(1, 5000): numeral = roman9.toRoman(integer) result = roman9.fromRoman(numeral) self.assertEqual(integer, result) class CaseCheck(unittest.TestCase): def testToRomanCase(self): """toRoman should always return uppercase""" for integer in range(1, 5000): numeral = roman9.toRoman(integer) self.assertEqual(numeral, numeral.upper()) def testFromRomanCase(self): """fromRoman should only accept uppercase input""" for integer in range(1, 5000): numeral = roman9.toRoman(integer) roman9.fromRoman(numeral.upper()) self.assertRaises(roman9.InvalidRomanNumeralError, roman9.fromRoman, numeral.lower()) if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/roman/stage9/roman9.py0000644000175000017500000000506610663321426023025 0ustar freeflyingfreeflying"""Convert to and from Roman numerals This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Steve Lamm, Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.3 $" __date__ = "$Date: 2004/05/05 21:57:20 $" __copyright__ = "Copyright (c) 2001 Steve Lamm, Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import re #Define exceptions class RomanError(Exception): pass class OutOfRangeError(RomanError): pass class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass #Roman numerals must be less than 5000 MAX_ROMAN_NUMERAL = 4999 #Define digit mapping romanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) #Create tables for fast conversion of roman numerals. #See fillLookupTables() below. toRomanTable = [ None ] # Skip an index since Roman numerals have no zero fromRomanTable = {} def toRoman(n): """convert integer to Roman numeral""" if not (0 < n <= MAX_ROMAN_NUMERAL): raise OutOfRangeError, "number out of range (must be 1..4999)" if int(n) <> n: raise NotIntegerError, "non-integers can not be converted" return toRomanTable[n] def fromRoman(s): """convert Roman numeral to integer""" if not s: raise InvalidRomanNumeralError, 'Input can not be blank' if not fromRomanTable.has_key(s): raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s return fromRomanTable[s] def toRomanDynamic(n): """convert integer to Roman numeral using dynamic programming""" assert(0 < n <= MAX_ROMAN_NUMERAL) assert(int(n) == n) result = "" for numeral, integer in romanNumeralMap: if n >= integer: result = numeral n -= integer break if n > 0: result += toRomanTable[n] return result def fillLookupTables(): """compute all the possible roman numerals""" #Save the values in two global tables to convert to and from integers. for integer in range(1, MAX_ROMAN_NUMERAL + 1): romanNumber = toRomanDynamic(integer) toRomanTable.append(romanNumber) fromRomanTable[romanNumber] = integer fillLookupTables() diveintopython-zh-5.4b/py/kgptest.py0000644000175000017500000000242710663321430020762 0ustar freeflyingfreeflying"""Unit test for kgp.py This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2001 Mark Pilgrim" __license__ = "Python" import unittest import sys if 'kgp' not in sys.path: sys.path.append('kgp') import kgp class KGPTest(unittest.TestCase): resultsMap = {"a":"0", "b":"1", "c":"2", "d":"", "e":"0", "f":"10", "g":"1"} def setUp(self): self.parser = kgp.KantGenerator('kgp/test.xml') def doTest(self, key): self.parser.loadSource('' % key) self.assertEqual(self.resultsMap[key], self.parser.refresh()) def testA(self): """kgp a ref test""" self.doTest("a") def testB(self): """kgp b ref test""" self.doTest("b") def testC(self): """kgp c ref test""" self.doTest("c") def testD(self): """kgp d ref test""" self.doTest("d") def testE(self): """kgp e ref test""" self.doTest("e") def testF(self): """kgp f ref test""" self.doTest("f") def testG(self): """kgp g ref test""" self.doTest("g") if __name__ == "__main__": unittest.main() diveintopython-zh-5.4b/py/fibonacci.py0000644000175000017500000000102410663321430021206 0ustar freeflyingfreeflying"""Fibonacci sequences using generators This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2004 Mark Pilgrim" __license__ = "Python" def fibonacci(max): a, b = 0, 1 while a < max: yield a a, b = b, a+b for n in fibonacci(1000): print n, diveintopython-zh-5.4b/py/piglatin.py0000644000175000017500000000201510663321430021101 0ustar freeflyingfreeflying"""Convert text to Pig Latin This program is part of "Dive Into Python", a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. """ __author__ = "Mark Pilgrim (mark@diveintopython.org)" __version__ = "$Revision: 1.2 $" __date__ = "$Date: 2004/05/05 21:57:19 $" __copyright__ = "Copyright (c) 2002 Mark Pilgrim" __license__ = "Python" import re def _wordToPigLatin(match): word = match.group() consonants = match.group(1) restOfWord = match.group(2) # put consonants after rest of word, and add "ay" result = "%s%say" % (restOfWord, consonants) # if word was all uppercase, make result uppercase if word == word.upper(): result = result.upper() # if word was capitalized, make result capitalized elif word == word.capitalize(): result = result.capitalize() return result def pigLatin(source): pattern = re.compile(r'\b([bcdfghjklmnpqrstvwxyz]*)(\w+)\b', re.IGNORECASE) return pattern.sub(_wordToPigLatin, source) diveintopython-zh-5.4b/py/openanything.py0000644000175000017500000000763710663321430022014 0ustar freeflyingfreeflying'''OpenAnything: a kind and thoughtful library for HTTP web services This program is part of 'Dive Into Python', a free Python book for experienced programmers. Visit http://diveintopython.org/ for the latest version. ''' __author__ = 'Mark Pilgrim (mark@diveintopython.org)' __version__ = '$Revision: 1.6 $'[11:-2] __date__ = '$Date: 2004/04/16 21:16:24 $' __copyright__ = 'Copyright (c) 2004 Mark Pilgrim' __license__ = 'Python' import urllib2, urlparse, gzip from StringIO import StringIO USER_AGENT = 'OpenAnything/%s +http://diveintopython.org/http_web_services/' % __version__ class SmartRedirectHandler(urllib2.HTTPRedirectHandler): def http_error_301(self, req, fp, code, msg, headers): result = urllib2.HTTPRedirectHandler.http_error_301( self, req, fp, code, msg, headers) result.status = code return result def http_error_302(self, req, fp, code, msg, headers): result = urllib2.HTTPRedirectHandler.http_error_302( self, req, fp, code, msg, headers) result.status = code return result class DefaultErrorHandler(urllib2.HTTPDefaultErrorHandler): def http_error_default(self, req, fp, code, msg, headers): result = urllib2.HTTPError( req.get_full_url(), code, msg, headers, fp) result.status = code return result def openAnything(source, etag=None, lastmodified=None, agent=USER_AGENT): """URL, filename, or string --> stream This function lets you define parsers that take any input source (URL, pathname to local or network file, or actual data as a string) and deal with it in a uniform manner. Returned object is guaranteed to have all the basic stdio read methods (read, readline, readlines). Just .close() the object when you're done with it. If the etag argument is supplied, it will be used as the value of an If-None-Match request header. If the lastmodified argument is supplied, it must be a formatted date/time string in GMT (as returned in the Last-Modified header of a previous request). The formatted date/time will be used as the value of an If-Modified-Since request header. If the agent argument is supplied, it will be used as the value of a User-Agent request header. """ if hasattr(source, 'read'): return source if source == '-': return sys.stdin if urlparse.urlparse(source)[0] == 'http': # open URL with urllib2 request = urllib2.Request(source) request.add_header('User-Agent', agent) if lastmodified: request.add_header('If-Modified-Since', lastmodified) if etag: request.add_header('If-None-Match', etag) request.add_header('Accept-encoding', 'gzip') opener = urllib2.build_opener(SmartRedirectHandler(), DefaultErrorHandler()) return opener.open(request) # try to open with native open function (if source is a filename) try: return open(source) except (IOError, OSError): pass # treat source as string return StringIO(str(source)) def fetch(source, etag=None, lastmodified=None, agent=USER_AGENT): '''Fetch data and metadata from a URL, file, stream, or string''' result = {} f = openAnything(source, etag, lastmodified, agent) result['data'] = f.read() if hasattr(f, 'headers'): # save ETag, if the server sent one result['etag'] = f.headers.get('ETag') # save Last-Modified header, if the server sent one result['lastmodified'] = f.headers.get('Last-Modified') if f.headers.get('content-encoding') == 'gzip': # data came back gzip-compressed, decompress it result['data'] = gzip.GzipFile(fileobj=StringIO(result['data'])).read() if hasattr(f, 'url'): result['url'] = f.url result['status'] = 200 if hasattr(f, 'status'): result['status'] = f.status f.close() return result diveintopython-zh-5.4b/py/colorize.py0000644000175000017500000001140010663321430021116 0ustar freeflyingfreeflying""" Colorize Python program listings embedded in HTML pages This script is used during the build process of "Dive Into Python" (http://diveintopython.org/) to recreate syntax highlighting of the Python program listings and code examples embedded in the HTML pages by wrapping Python keywords in or tags. The following tags are presumed to contain Python code:
...
... (These tags are generated automatically by the DocBook XSL stylesheets when the book is transformed from XML to HTML.) Looks for 2 arguments on the command line. The first argument is a file or directory. If a file, the file is processed; if a directory, all .html files in the directory are processed. The second argument, if given, is a flag for the type of tags to wrap around keywords. 0 (default) - use tags, where xxx in ('comment', 'string', 'keyword', 'function', 'class'). Actual syntax highlighting must be defined in a