Beginner: Data type conversion question
I am still fairly new to python and programming in general. My
question is regarding data conversion, I am working on a script that
will edit dns zone files, one of the functions i wrote handles
updating the serial number.
Our zone files use the date as the first part of the serial and a two
digit integer as the last two.
i.e. 2009011501. The next update would be 2009011502, etc
Here is the function I wrote, I am using dnspython for reading in zone
files as Zone "objects". Because dnspython's built-in serial updater
will not work with how we format our serial's, I have to re-write it.
def checkSerial():
"""
Checks the current 'date' portion of the serial number and
checks the current 'counter'(the two digit number at the end of
the serial number), then returns a complete new serial
"""
currentDate = time.strftime("%Y""%m""%d", time.localtime())
for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
date = str(rdata.serial)[0:8]
inc = str(rdata.serial)[8:10]
if date == currentDate:
int(inc) + 1
print inc
newInc = str(inc).zfill(2)
serial = date + newInc
print "date is the same"
return serial
elif date < currentDate:
newInc = "01".zfill(2)
serial = currentDate + newInc
print "date is different"
return serial
Through all of this I am doing a lot of data type conversion. string -
> integer, integer back to string, etc. Is this an efficient way of
handling this? I have to perform basic addition on the "inc"
variable, but also need to expose that value as a string. What I
have above does work, but I can't help but think there is a more
efficient way. I guess I am not used to data types being converted so
easily.
--
http://mail.python.org/mailman/listinfo/python-list
Re: Beginner: Data type conversion question
On Jan 15, 9:16 pm, Chris Rebert wrote:
> On Thu, Jan 15, 2009 at 9:09 PM, flagg wrote:
> > I am still fairly new to python and programming in general. My
> > question is regarding data conversion, I am working on a script that
> > will edit dns zone files, one of the functions i wrote handles
> > updating the serial number.
> > Our zone files use the date as the first part of the serial and a two
> > digit integer as the last two.
>
> > i.e. 2009011501. The next update would be 2009011502, etc
> > Here is the function I wrote, I am using dnspython for reading in zone
> > files as Zone "objects". Because dnspython's built-in serial updater
> > will not work with how we format our serial's, I have to re-write it.
>
> > def checkSerial():
> > """
> > Checks the current 'date' portion of the serial number and
> > checks the current 'counter'(the two digit number at the end of
> > the serial number), then returns a complete new serial
> > """
> > currentDate = time.strftime("%Y""%m""%d", time.localtime())
> > for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
> > date = str(rdata.serial)[0:8]
> > inc = str(rdata.serial)[8:10]
> > if date == currentDate:
> > int(inc) + 1
>
> The previous line is pointless. It's like having '4+4' as a statement
> on its own line. It calculates a value but doesn't change any state or
> even use the value. Perhaps you instead meant?:
> inc = int(inc) + 1
>
> Cheers,
> Chris
>
> --
> Follow the path of the Iguana...http://rebertia.com
Ah thank you. Oversight on my part. That explains why that if
statement never incremented the counter correctly. Anything odd about
how I'm converting back and forth between different data types as
often as I am? Is that common practice is normal programming?
(forgive the beginner questions)
--
http://mail.python.org/mailman/listinfo/python-list
Re: Beginner: Data type conversion question
On Jan 15, 11:35 pm, Terry Reedy wrote:
> flagg wrote:
> > I am still fairly new to python and programming in general. My
> > question is regardingdataconversion, I am working on a script that
> > will edit dns zone files, one of the functions i wrote handles
> > updating the serial number.
> > Our zone files use the date as the first part of the serial and a two
> > digit integer as the last two.
>
> > i.e. 2009011501. The next update would be 2009011502, etc
> > Here is the function I wrote, I am using dnspython for reading in zone
> > files as Zone "objects". Because dnspython's built-in serial updater
> > will not work with how we format our serial's, I have to re-write it.
>
> > def checkSerial():
> > """
> > Checks the current 'date' portion of the serial number and
> > checks the current 'counter'(the two digit number at the end of
> > the serial number), then returns a complete new serial
> > """
> > currentDate = time.strftime("%Y""%m""%d", time.localtime())
> > for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
> > date = str(rdata.serial)[0:8]
> > inc = str(rdata.serial)[8:10]
>
> If rdate.serial is already a string, as name would imply, the str() call
> is pointless. If not, can you get inc as int more directly?
>
>
>
> > if date == currentDate:
> > int(inc) + 1
> > print inc
> > newInc = str(inc).zfill(2)
> > serial = date + newInc
> > print "date is the same"
> > return serial
> > elif date < currentDate:
> > newInc = "01".zfill(2)
> > serial = currentDate + newInc
> > print "date is different"
> > return serial
>
> > Through all of this I am doing a lot ofdatatypeconversion. string -
> >> integer, integer back to string, etc. Is this an efficient way of
> > handling this? I have to perform basic addition on the "inc"
> > variable, but also need to expose that value as a string. What I
> > have above does work, but I can't help but think there is a more
> > efficient way. I guess I am not used todatatypes being converted so
> > easily.
>
> Other than that, you are perhaps worrying too much, even if code could
> be squeezed more. The idea that every object knows how to convert
> itself to a string representation is basic to Python.
>
> tjr
Actually when i run a type(serial) on that variable it returns a
"long" which i am not sure why dnspython uses a long variable to
store the serial. But you could be right about me worrying to much.
The other languages I have dabbled in (java, perl) I don't remember
type conversion being as simple. But again I am still new, so don't
quote me on that :)
--
http://mail.python.org/mailman/listinfo/python-list
Re: Beginner: Data type conversion question
On Jan 15, 11:43 pm, Marc 'BlackJack' Rintsch wrote:
> On Thu, 15 Jan 2009 21:09:43 -0800, flagg wrote:
> > def checkSerial():
> > """
> > Checks the current 'date' portion of the serial number and checks
> > the current 'counter'(the two digit number at the end of the serial
> > number), then returns a complete new serial """
> > currentDate = time.strftime("%Y""%m""%d", time.localtime())
>
> The format string can be written as *one* string literal instead of
> three: "%Y%m%d".
>
> > for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
> > date = str(rdata.serial)[0:8]
> > inc = str(rdata.serial)[8:10]
>
> Here you are converting `rdata.serial` twice.
>
> tmp = str(rdata.serial)
> date = tmp[0:8]
> inc = int(tmp[8:10])
>
> As `inc` is conceptually a number, you should do theconversionhere and
> treat it as number from now on.
>
> > if date == currentDate:
> > int(inc) + 1
> > print inc
> > newInc = str(inc).zfill(2)
> > serial = date + newInc
> > print "date is the same"
> > return serial
> > elif date < currentDate:
> > newInc = "01".zfill(2)
> > serial = currentDate + newInc
> > print "date is different"
> > return serial
>
> Both branches do almost the same. You should try to avoid such code
> duplication.
>
> if date == currentDate:
> inc += 1
> elif date < currentDate:
> inc = 1
> else:
> assert False # Should never happen.
>
> return "%s%02d" % (date, inc)
>
> That's it.
>
> Ciao,
> Marc 'BlackJack' Rintsch
Ah
return "%s%02d" % (date, inc)
This piece is what I was missing in my original design. I couldn't
figure out hot to take and integer and force it to my double digit.
i.e. 01 instead of 1. Which is why I was using strings to make that
happen. (obviously incorrectly). Thanks
Could you explain what "assert" does in the if statement. I am
assuming if the first two conditions are not met, it will hit "assert
false" and exit the program?
--
http://mail.python.org/mailman/listinfo/python-list
SimpleXMLRPCServer question
I am working on a very basic xmlrpc server, which will expose certain functions for administering BIND zone files. The big problem I am having is parsing the incoming xmlrpc request. Basically part of the xmlrpc request will help deterime which zone file is edited.I have been looking at the do_POST() method from SimpleXMLRPCDispatcher and it seems like I could code something which overides that method, however I am new to programming am at a loss, i might even be making this tougher than it needs to be. Is there a way to parse the incoming xmlrpc request before the function it is calling is executed? -- http://mail.python.org/mailman/listinfo/python-list
Re: SimpleXMLRPCServer question
On Jan 30, 8:12 pm, [email protected] wrote: > Quoth flagg : > > > I am working on a very basic xmlrpc server, which will expose certain > > functions for administering BIND zone files. The big problem I am > > having is parsing the incoming xmlrpc request. Basically part of the > > xmlrpc request will help deterime which zone file is edited. I have > > been looking at the do_POST() method from SimpleXMLRPCDispatcher and > > it seems like I could code something which overides that method, > > however I am new to programming am at a loss, i might even be making > > this tougher than it needs to be. Is there a way to parse the > > incoming xmlrpc request before the function it is calling is executed? > > Wouldn't you be overriding '_dispatch' on SimpleXMLRPCServer instead? > > It's been a while since I looked at XMLRPC, but why wouldn't you have > a operation names, with the zone file to operate on as an argument? > Then you'd just be defining your operations as methods on your > SimpleXMLRPCServer, and they'd use the argument to determine which file > to operate on. > > If that doesn't make sense, either I've forgotten how XMLRPC works, > or you should explain your requirements a bit more. > > --RDM Let me see if i can elaborate on the requirements. I have 20+ different zone files. I want the xmlrpc server to be able to determine what zone file to open by looking at the incoming xml request. For example one of the functions I have now is to show a DNS record (I am using dnspython for most of this work) If i send an xmlrpc request that uses the 'showRecord' function with params of 'oracle1.foo.bar.com' I want to parse the "params" piece and then instruct the xml-rpc server to open foo.bar.com.zone for reading. The reason why i was looking at do_Post() and _dispatch was to attempt to read the incoming params and do exactly that. Do you think there is an easier way of accomplishing this, than the way I am going about it? -- http://mail.python.org/mailman/listinfo/python-list
Re: SimpleXMLRPCServer question
On Feb 1, 12:38 am, "Hendrik van Rooyen" wrote: > "flagg" wrote: > >Let me see if i can elaborate on the requirements. I have 20+ > >different zone files. I want the xmlrpc server to be able to > >determine what zone file to open by looking at the incoming xml > >request. For example one of the functions I have now is to show a DNS > >record (I am using dnspython for most of this work) > > This is a wrong move, it is too magical - see below > > >If i send an xmlrpc request that uses the 'showRecord' function with > >params of 'oracle1.foo.bar.com' I want to parse the "params" piece > >and then instruct the xml-rpc server to open foo.bar.com.zone for > >reading. The reason why i was looking at do_Post() and _dispatch was > >to attempt to read the incoming params and do exactly that. > > >Do you think there is an easier way of accomplishing this, than the > >way I am going about it? > > Yes I do. > > Why don't you split the functionality into two bits - exactly as if you were > doing > it locally: > > - OpenTheThing(whatOrWhere) > - ReadTheRecordAndShowIt(PossiblyWhichRecord) > > If it's a remote database you are accessing, then you may need even more > steps, like first doing some select, or whatever - I would get it running > locally, calling local functions directly on the server, and then make them > remote xmlrpc proxy functions, after it's all working. > > If you are getting the request from some user input, you can either change > the way you ask the questions, or you do the parsing at point of origen, to > determine what to call, in which sequence. > > - Hendrik Actually I have it working as local functions, its wrapping those local functions up in a way that makes sense that is throwing me off. Your suggestion of making two functions one for opening the file and one for showing records makes sense. I will give it a shot -- http://mail.python.org/mailman/listinfo/python-list
Code critique xmlrpclib
This xmlrpc server is designed to parse dns zone files and then
perform various actions on said files. \
It uses dnspython, and xmlrpclib
I'd like to know what some of the more experienced python users
think. Where I could improve code, make it more efficient, whatever.
All suggestions are welcome. This is my first functional python
program, and I have tons of questions to go along with whatever
suggestions. How could I do sanity checking; right now nothing
checks the input to these functions, error-handling in this program is
almost non-existant how do you integrate decent error handling into a
piece of software..ill shut up now.
Thanks
import dns.zone
from time import localtime, strftime, time
import os, sys
from dns.rdataclass import *
from dns.rdatatype import *
from string import Template
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
zoneDir = "/dns"
def openZoneFile(zoneFile):
"""
Opens a zone file. Then reads in zone file to dnspython zone
object.
"""
global zone
global host
global domain
domain = ".".join(zoneFile.split('.')[1:])
host = ".".join(zoneFile.split('.')[:1])
try:
zone = dns.zone.from_file(zoneDir + domain + '.zone',
domain)
except dns.exception, e:
print e.__class__, e
class DNSFunctions:
# Not exposed to xml-rpc calls, used internally only.
def _writeToZoneFile(self, record):
"""
Checks if zone file exists, if it does it write values to zone
file
"""
for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
new_serial = int(strftime('%Y%m%d00', localtime(time(
if new_serial <= rdata.serial:
new_serial = rdata.serial + 1
rdata.serial = new_serial
if os.path.exists(zoneDir + str(zone.origin) + "zone"):
f = open(zoneDir + str(zone.origin) + "zone", "w")
zone.to_file(f)
f.close()
else:
print "Zone: " + zone.origin + " does not exist, please
add first"
def showRecord(self, record):
"""
Shows a record for a given zone. Prints out
TTL, IN, Record Type, IP
"""
openZoneFile(record)
try:
rdataset = zone.get_node(host)
for rdata in rdataset:
return str(rdata)
except:
raise Exception("Record not found")
def changeRecord(self, record, type, target):
"""
Changes a dns entry.
@param record: which record to chance
@param type: what type of record, A, MX, NS, CNAME
@target: if CNAME target points to HOSTNAME, if A record
points to IP
"""
openZoneFile(record)
try:
rdataset = zone.find_rdataset(host, rdtype=type)
except:
raise Exception("You must enter a valid record and type.
See --usage for examples")
for rdata in rdataset:
if rdata.rdtype == CNAME:
rdata.target = dns.name.Name((target,))
elif rdata.rdtype == A:
rdata.address = target
else:
assert False
self._writeToZoneFile(host)
def deleteRecord(self, record):
"""
Delete Entry from zone file
"""
openZoneFile(record)
zone.delete_node(host)
self._writeToZoneFile(record)
def addRecord(self, record, type, target):
"""
Adds a new record to zone file
"""
openZoneFile(record)
rdataset = zone.find_rdataset(host, rdtype=type, create=True)
if rdataset.rdtype == A:
rdata = dns.rdtypes.IN.A.A(IN, A, address = target)
rdataset.add(rdata, ttl=300)
elif rdataset.rdtype == CNAME:
rdata = dns.rdtypes.ANY.CNAME.CNAME(IN, CNAME,
dns.name.Name((target,)))
rdataset.add(rdata, ttl=300)
else:
assert False
self._writeToZoneFile(host)
def addZoneFile(self, file):
"""
Function to create a new empty zone file, if none exists. If
exists
function will terminate.
"""
newZoneSerial = strftime("%Y%m%d00", localtime())
zoneTemplate = Template('''$$TTL${ttltime}
$$ORIGIN ${domain}.
@ 5M IN SOA nsrepo1.foobar.priv.
dnsadmin.foobar.priv. (
; did you update reverse?!
${serial} ; Serial CCYYMMDDxx where xx is
todays edit
1H
10M
1D
60M
)''')
if not os.path.exists(zoneDir + file + ".zone"):
f = open(zoneDir + file + ".zone", "w")
f.write(zoneTemplate.substitute({'ttltime':'300',
'domain': file, 'serial': newZoneSerial}))
f.close()
else:
print "Zone: " + f
Re: Code critique xmlrpclib
On Feb 3, 7:32 am, Nick Craig-Wood wrote:
> flagg wrote:
> > This xmlrpc server is designed to parse dns zone files and then
> > perform various actions on said files. \
> > It uses dnspython, and xmlrpclib
> > I'd like to know what some of the more experienced python users
> > think. Where I could improve code, make it more efficient, whatever.
> > All suggestions are welcome. This is my first functional python
> > program, and I have tons of questions to go along with whatever
> > suggestions. How could I do sanity checking; right now nothing
> > checks the input to these functions, error-handling in this program is
> > almost non-existant how do you integrate decent error handling into a
> > piece of software..ill shut up now.
>
> I made a few comments, some about error handling! See below
>
>
>
> > import dns.zone
> > from time import localtime, strftime, time
> > import os, sys
> > from dns.rdataclass import *
> > from dns.rdatatype import *
> > from string import Template
> > import xmlrpclib
> > from SimpleXMLRPCServer import SimpleXMLRPCServer
> > from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
>
> > zoneDir = "/dns"
>
> > def openZoneFile(zoneFile):
> > """
> > Opens a zone file. Then reads in zone file to dnspython zone
> > object.
> > """
> > global zone
> > global host
> > global domain
> > domain = ".".join(zoneFile.split('.')[1:])
> > host = ".".join(zoneFile.split('.')[:1])
>
> > try:
> > zone = dns.zone.from_file(zoneDir + domain + '.zone',
> > domain)
> > except dns.exception, e:
> > print e.__class__, e
>
> Don't use global variables!
>
> This function should probably return 3 things
>
> return zone, host, domain
>
> And whenever you use it, say
>
> zone, host, domain = openZoneFile(xxx)
>
> It should probably be a method of DNSFunctions. I'd avoid setting
> self.zone etc as that is making a different sort of global data which
> I'd avoid too.
>
> Also if the dns.zone.from_file didn't work (raises dns.exception) you
> set the host and domain but the zone is left at its previous value
> which probably isn't what you wanted. I'd let the error propagate
> which I think will do something sensible for the xmlrpc.
>
>
>
> > class DNSFunctions:
>
> > # Not exposed to xml-rpc calls, used internally only.
> > def _writeToZoneFile(self, record):
> > """
> > Checks if zone file exists, if it does it write values to zone
> > file
> > """
>
> > for (name, ttl, rdata) in zone.iterate_rdatas(SOA):
> > new_serial = int(strftime('%Y%m%d00', localtime(time(
> > if new_serial <= rdata.serial:
> > new_serial = rdata.serial + 1
> > rdata.serial = new_serial
>
> > if os.path.exists(zoneDir + str(zone.origin) + "zone"):
> > f = open(zoneDir + str(zone.origin) + "zone", "w")
> > zone.to_file(f)
> > f.close()
> > else:
> > print "Zone: " + zone.origin + " does not exist, please
> > add first"
>
> This should probably be raising an exception to be caught or
> propagated back to the client via xmlrpc.
>
>
>
>
>
> > def showRecord(self, record):
> > """
> > Shows a record for a given zone. Prints out
> > TTL, IN, Record Type, IP
> > """
>
> > openZoneFile(record)
>
> > try:
> > rdataset = zone.get_node(host)
> > for rdata in rdataset:
> > return str(rdata)
> > except:
> > raise Exception("Record not found")
>
> > def changeRecord(self, record, type, target):
> > """
> > Changes a dns entry.
> > �...@param record: which record to chance
> > �...@param type: what type of record, A, MX, NS, CNAME
> > �...@target: if CNAME target points to HOSTNAME, if A record
> > points to IP
> > """
> > openZoneFile(record)
> > try:
> >
