Reupload, How do i convert a php file to python dictionary? - python
After going over de fora, i did not find something that could solve this issue properly. I want to convert a file written in php to a python dictionary. In this case this file is a converted TrueType Font-file.
<?php
$type = 'TrueType';
$name = 'Calibri';
$desc = array('Ascent'=>750,'Descent'=>-250,'CapHeight'=>632,'Flags'=>32,'FontBBox'=>'[-503 -313 1240 1026]','ItalicAngle'=>0,'StemV'=>70,'MissingWidth'=>507);
$up = -113;
$ut = 65;
$cw = array(
chr(0)=>507,chr(1)=>507,chr(2)=>507,chr(3)=>507,chr(4)=>507,chr(5)=>507,chr(6)=>507,chr(7)=>507,chr(8)=>507,chr(9)=>507,chr(10)=>507,chr(11)=>507,chr(12)=>507,chr(13)=>507,chr(14)=>507,chr(15)=>507,chr(16)=>507,chr(17)=>507,chr(18)=>507,chr(19)=>507,chr(20)=>507,chr(21)=>507,
chr(22)=>507,chr(23)=>507,chr(24)=>507,chr(25)=>507,chr(26)=>507,chr(27)=>507,chr(28)=>507,chr(29)=>507,chr(30)=>507,chr(31)=>507,' '=>226,'!'=>326,'"'=>401,'#'=>498,'$'=>507,'%'=>715,'&'=>682,'\''=>221,'('=>303,')'=>303,'*'=>498,'+'=>498,
','=>250,'-'=>306,'.'=>252,'/'=>386,'0'=>507,'1'=>507,'2'=>507,'3'=>507,'4'=>507,'5'=>507,'6'=>507,'7'=>507,'8'=>507,'9'=>507,':'=>268,';'=>268,'<'=>498,'='=>498,'>'=>498,'?'=>463,'#'=>894,'A'=>579,
'B'=>544,'C'=>533,'D'=>615,'E'=>488,'F'=>459,'G'=>631,'H'=>623,'I'=>252,'J'=>319,'K'=>520,'L'=>420,'M'=>855,'N'=>646,'O'=>662,'P'=>517,'Q'=>673,'R'=>543,'S'=>459,'T'=>487,'U'=>642,'V'=>567,'W'=>890,
'X'=>519,'Y'=>487,'Z'=>468,'['=>307,'\\'=>386,']'=>307,'^'=>498,'_'=>498,'`'=>291,'a'=>479,'b'=>525,'c'=>423,'d'=>525,'e'=>498,'f'=>305,'g'=>471,'h'=>525,'i'=>229,'j'=>239,'k'=>455,'l'=>229,'m'=>799,
'n'=>525,'o'=>527,'p'=>525,'q'=>525,'r'=>349,'s'=>391,'t'=>335,'u'=>525,'v'=>452,'w'=>715,'x'=>433,'y'=>453,'z'=>395,'{'=>314,'|'=>460,'}'=>314,'~'=>498,chr(127)=>507,chr(128)=>507,chr(129)=>507,chr(130)=>250,chr(131)=>305,
chr(132)=>418,chr(133)=>690,chr(134)=>498,chr(135)=>498,chr(136)=>395,chr(137)=>1038,chr(138)=>459,chr(139)=>339,chr(140)=>867,chr(141)=>507,chr(142)=>468,chr(143)=>507,chr(144)=>507,chr(145)=>250,chr(146)=>250,chr(147)=>418,chr(148)=>418,chr(149)=>498,chr(150)=>498,chr(151)=>905,chr(152)=>450,chr(153)=>705,
chr(154)=>391,chr(155)=>339,chr(156)=>850,chr(157)=>507,chr(158)=>395,chr(159)=>487,chr(160)=>226,chr(161)=>326,chr(162)=>498,chr(163)=>507,chr(164)=>498,chr(165)=>507,chr(166)=>498,chr(167)=>498,chr(168)=>393,chr(169)=>834,chr(170)=>402,chr(171)=>512,chr(172)=>498,chr(173)=>306,chr(174)=>507,chr(175)=>394,
chr(176)=>339,chr(177)=>498,chr(178)=>336,chr(179)=>334,chr(180)=>292,chr(181)=>550,chr(182)=>586,chr(183)=>252,chr(184)=>307,chr(185)=>246,chr(186)=>422,chr(187)=>512,chr(188)=>636,chr(189)=>671,chr(190)=>675,chr(191)=>463,chr(192)=>579,chr(193)=>579,chr(194)=>579,chr(195)=>579,chr(196)=>579,chr(197)=>579,
chr(198)=>763,chr(199)=>533,chr(200)=>488,chr(201)=>488,chr(202)=>488,chr(203)=>488,chr(204)=>252,chr(205)=>252,chr(206)=>252,chr(207)=>252,chr(208)=>625,chr(209)=>646,chr(210)=>662,chr(211)=>662,chr(212)=>662,chr(213)=>662,chr(214)=>662,chr(215)=>498,chr(216)=>664,chr(217)=>642,chr(218)=>642,chr(219)=>642,
chr(220)=>642,chr(221)=>487,chr(222)=>517,chr(223)=>527,chr(224)=>479,chr(225)=>479,chr(226)=>479,chr(227)=>479,chr(228)=>479,chr(229)=>479,chr(230)=>773,chr(231)=>423,chr(232)=>498,chr(233)=>498,chr(234)=>498,chr(235)=>498,chr(236)=>229,chr(237)=>229,chr(238)=>229,chr(239)=>229,chr(240)=>525,chr(241)=>525,
chr(242)=>527,chr(243)=>527,chr(244)=>527,chr(245)=>527,chr(246)=>527,chr(247)=>498,chr(248)=>529,chr(249)=>525,chr(250)=>525,chr(251)=>525,chr(252)=>525,chr(253)=>453,chr(254)=>525,chr(255)=>453);
$enc = 'cp1252';
$uv = array(0=>array(0,128),128=>8364,130=>8218,131=>402,132=>8222,133=>8230,134=>array(8224,2),136=>710,137=>8240,138=>352,139=>8249,140=>338,142=>381,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),152=>732,153=>8482,154=>353,155=>8250,156=>339,158=>382,159=>376,160=>array(160,96));
$file = 'calibri.z';
$originalsize = 77252;
$subsetted = true;
?>
to:
font = {"type":"TrueType",
"name":"Calibri",
"desc":{"Ascent":750,etc...},
etc......
}
I thank all in advance!
P.S. I reuploaded this question (my previous was closed) to share my solution in case someone else needs it.
The solution i found was just writing the parsing myself:
import re
import regex
def parse_php(fontfile):
font_dict = {}
for item in php_chunks(fontfile):
key, attr = item.split(" = ")
attr = attr.replace("\t","").strip()
attr = re.sub("^(.*);",r"\1",attr)
# re.split("[,](?!'=>)",data["cw"])
if re.match("'(.*)'",attr):
attr = re.sub("'(.*)'",r"\1",attr)
try:
attr = eval(attr)
font_dict[key.replace("$","").strip()] = attr
except:
if "array" in attr:
if re.match("^array\(",attr):
attr_dict = {}
attr = re.sub("array\((.*)\)",r"\1",attr)
attr = regex.split("(?<!array\(\d*)[,](?!'=>)",attr)
for row in attr:
dict_key, dict_item = row.strip().split("=>")
try:
attr_dict[str(eval(dict_key))] = eval(dict_item)
except:
attr_dict[str(eval(dict_key))] = dict_item
font_dict[key.replace("$","").strip()] = attr_dict
else:
font_dict[key.replace("$","").strip()] = attr
return font_dict
def php_chunks(raw):
raw = raw.read()
chunk = ""
for idx, line in enumerate(raw.splitlines()):
if line.startswith("$"):
if idx != 1:
yield chunk
chunk = ""
chunk = "".join(line)
else:
chunk = "".join([chunk,line])
Related
What's the best method to create a dictionary from outputs of multiple for loops
This is my code: def get_coin_tickers(url): req = requests.get(url) # print(req.text) resp = json.loads(req.text) # print(resp.text) return resp pair_a_list = ["BTC_USDT", "EOS_USDT", "ETH_USDT"] pair_b_list = ["SOL_USDT", "MATIC_USDT", "SUSHI_USDT"] for pair_a in pair_a_list: orderbook_url = f'https://api.pionex.com/api/v1/market/depth?symbol={pair_a}&limit=5' pair_a_prices_json = get_coin_tickers(orderbook_url) pair_a_ask = pair_a_prices_json['data']['asks'][0][0] pair_a_bid = pair_a_prices_json['data']['bids'][0][0] for pair_b in pair_b_list: orderbook_url = f'https://api.pionex.com/api/v1/market/depth?symbol={pair_b}&limit=5' pair_a_prices_json = get_coin_tickers(orderbook_url) pair_b_ask = pair_a_prices_json['data']['asks'][0][0] pair_b_bid = pair_a_prices_json['data']['bids'][0][0] keys = ['pair_a', 'pair_a_ask', 'pair_a_bid', 'pair_b', 'pair_b_ask', 'pair_b_bid'] values = [pair_a, pair_a_ask, pair_a_bid, pair_b, pair_b_ask, pair_b_bid] mydict = {k: v for (k, v) in zip(keys, values)} print(mydict) I'm able to create a Dictionary but with only one Symbol-Pairs from each list. Which seems to be outputs from only the last symbol pairs of both the lists: {'pair_a': 'ETH_USDT', 'pair_a_ask': '1254.18', 'pair_a_bid': '1253.51', 'pair_b': 'SUSHI_USDT', 'pair_b_ask': '0.9815', 'pair_b_bid': '0.9795'} I'm expecting to see a combined dictionary with values of both lists as keys (with their API-Values) in the final list (after) iterating through both lists using for Loops
Found a solution to my question based on suggestion from #JonSG, plus adapted to the suggestion. I've included the code below for others to use as and if the need arises. for pair_a_list, pair_b_list, pair_c_list in zip(pair_a_list, pair_b_list, pair_c_list): orderbook_a_url = f'https://api.pionex.com/api/v1/market/depth?symbol={pair_a_list}&limit=1' pair_a_prices_json = get_coin_tickers(orderbook_a_url) pair_a_ask = pair_a_prices_json['data']['asks'][0][0] pair_a_bid = pair_a_prices_json['data']['bids'][0][0] my_dict_a = { 'pair_a_ask': pair_a_ask, 'pair_a_bid': pair_a_bid } orderbook_b_url = f'https://api.pionex.com/api/v1/market/depth?symbol={pair_b_list}&limit=1' pair_b_prices_json = get_coin_tickers(orderbook_b_url) pair_b_ask = pair_b_prices_json['data']['asks'][0][0] pair_b_bid = pair_b_prices_json['data']['bids'][0][0] my_dict_b = { 'pair_b_ask': pair_b_ask, 'pair_b_bid': pair_b_bid } orderbook_c_url = f'https://api.pionex.com/api/v1/market/depth?symbol={pair_c_list}&limit=1' pair_c_prices_json = get_coin_tickers(orderbook_c_url) pair_c_ask = pair_c_prices_json['data']['asks'][0][0] pair_c_bid = pair_c_prices_json['data']['bids'][0][0] my_dict_c = { 'pair_c_ask': pair_c_ask, 'pair_c_bid': pair_c_bid } # (Use either option below.) # my_dict = {**my_dict_a, **my_dict_b, **my_dict_c} # my_dict = my_dict_a | my_dict_b | my_dict_c
List index errror
I have created a program which reads a file line into a list. When i run the code below, i see that there is a list with elements inside it. dogs_list_player = [] dogs_list_computer = [] with open("dogs.txt") as f: for i in range(Y): dogs_list_player.append(f.readline().splitlines()) print(dogs_list_player) for i in range(Z): dogs_list_computer.append(f.readline().splitlines()) print(dogs_list_computer) The result is: [['Tim']] [['Tim'], ['Bob']] [['Tim'], ['Bob'], ['Jess']] [['Tim'], ['Bob'], ['Jess'], ['Bess']] [['Tim'], ['Bob'], ['Jess'], ['Bess'], ['Tess']] [['Dom']] [['Dom'], ['Tom']] [['Dom'], ['Tom'], ['Will']] [['Dom'], ['Tom'], ['Will'], ['Ben']] [['Dom'], ['Tom'], ['Will'], ['Ben'], ['Joe']] But the issue arises when i add this part of code: dogs_list_player = [] dogs_list_computer = [] with open("dogs.txt") as f: for i in range(Y): dogs_list_player.append(f.readline().splitlines()) print(dogs_list_player) for i in range(Z): dogs_list_computer.append(f.readline().splitlines()) print(dogs_list_computer) class Dog_card: name = "" friendliness = "" intelligence = "" exercise = "" drool = "" def printing_card(self): prnt_str = "Name:%s \nIntelligence:%s \nExercise:%s \nDrool:%s" %(self.name, self.friendliness, self.intelligence, self.exercise, self.drool) return prnt_str player_card = Dog_card() card_count = 0 player.name = dogs_list_player[0]#i think this is where the issue is happening the result of this code is: IndexError: list index out of range Any help would be appreciated
your Dog_card class has some errors : you forget "friendliness" parameter in the string that is in printing_card method and also you have not any constructor in your class . class Dog_card: def __init__(self): self.name = "" self.friendliness = "" self.intelligence = "" self.exercise = "" self.drool = "" def printing_card(self): prnt_str = "Name:%s \nIntelligence:%s friendliness:%s \nExercise:%s \nDrool:%s" %(self.name, self.friendliness, self.intelligence, self.exercise, self.drool) return prnt_str this shoud be work .
Extracting data from string with specific format using Python
I am novice with Python and currently I am trying to use it to parse some custom output formated string. In fact format contains named lists of float and lists of tuples of float. I wrote a function but it looks excessive. How can it be done in more suitable way for Python? import re def extract_line(line): line = line.lstrip('0123456789# ') measurement_list = list(filter(None, re.split(r'\s*;\s*', line))) measurement = {} for elem in measurement_list: elem_list = list(filter(None, re.split(r'\s*=\s*', elem))) name = elem_list[0] if name == 'points': points = list(filter(None, re.split(r'\s*\(\s*|\s*\)\s*',elem_list[1].strip(' {}')))) for point in points: p = re.match(r'\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*', point).groups() if 'points' not in measurement.keys(): measurement['points'] = [] measurement['points'].append(tuple(map(float,p))) else: values = list(filter(None, elem_list[1].strip(' {}').split(' '))) for value in values: if name not in measurement.keys(): measurement[name] = [] measurement[name].append(float(value)) return measurement to_parse = '#10 points = { ( 2.96296 , 0.822213 ) ( 3.7037 , 0.902167 ) } ; L = { 5.20086 } ; P = { 3.14815 3.51852 } ;' print(extract_line(to_parse))
You can do it using re.findall: import re to_parse = '#10 points = { ( 2.96296 , 0.822213 ) ( 3.7037 , 0.902167 ) } ; L = { 5.20086 } ; P = { 3.14815 3.51852 } ;' m_list = re.findall(r'(\w+)\s*=\s*{([^}]*)}', to_parse) measurements = {} for k,v in m_list: if k == 'points': elts = re.findall(r'([0-9.]+)\s*,\s*([0-9.]+)', v) measurements[k] = [tuple(map(float, elt)) for elt in elts] else: measurements[k] = [float(x) for x in v.split()] print(measurements) Feel free to put it in a function and to check if keys don't already exists.
This: import re a=re.findall(r' ([\d\.eE-]*) ',to_parse) map(float, a) >> [2.96296, 0.822213, 3.7037, 0.902167, 5.20086, 3.14815] Will give you your list of numbers, is that what you look for?
Trying to avoid creating numerous variables in python
I am new to python and I have a lot of variables I will be using in this script. These variables are being used to grab data from each column in an uploaded file. I have added variables for each object type and I have about 12 more object types to add. Isn't there a better way I can do this? I have the file it's grabbing data from here: Action Object Solution ID hostgroup_name alias Add Host Group ISD-CR ISD-CR_database ISD-CR Database Add Service ISD-CR ISD-CR_database Update Service Group ISD-CR ISD-CR Database Delete Service ISD-CR ISD-CR_database Here is the script I have so far. from pynag import Model from pynag.Parsers import config def addObject(): # Add hostgroup object hg = Model.Hostgroup() hg.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name)) # Adding all attributes to allow any to be added if needed hg.hostgroup_name = target_hostgroup_name hg.alias = target_alias hg.members = target_members hg.hostgroup_members = target_hostgroup_members hg.notes = target_notes hg.notes_url = target_notes_url hg.action_url = target_action_url # Save hg.save() print "hostgroup added" # Add service object s = Model.Service() s.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name)) # Adding all attributes to allow any to be added if needed s.host_name = target_host_name s.hostgroup_name = target_hostgroup_name s.service_description = target_service_description s.display_name = target_display_name s.servicegroups = target_servicegroups s.is_volatile = target_is_volatile s.check_command = target_check_command s.initial_state = target_initial_state s.max_check_attempts = target_max_check_attempts s.check_interval = target_check_interval s.retry_interval = target_retry_interval s.active_checks_enabled = target_active_checks_enabled s.passive_checks_enabled = target_passive_checks_enabled s.check_period = target_check_period s.obsess_over_service = target_obsess_over_service s.check_freshness = target_check_freshness s.freshness_threshold = target_freshness_threshold s.event_handler = target_event_handler s.event_handler_enabled = target_event_handler_enabled s.low_flap_threshold = target_low_flap_threshold s.high_flap_threshold = target_high_flap_threshold s.flap_detection_enabled = target_flap_detection_enabled s.flap_detection_options = target_flap_detection_options s.process_perf_data = target_process_perf_data s.retain_status_information = target_retain_status_information s.retain_nonstatus_information = target_retain_nonstatus_information s.notification_interval = target_notification_interval s.first_notification_delay = target_first_notification_delay s.notification_period = target_notification_period s.notification_options = target_notification_options s.notification_enabled = target_notifications_enabled s.contacts = target_contacts s.contact_groups = target_contact_groups s.stalking_options = target_stalking_options s.notes = target_notes s.notes_url = target_notes_url s.action_url = target_action_url s.icon_image = target_icon_image s.icon_image_alt = target_icon_image_alt # Save s.save() print "service added" # Add servicegroup object sg = Model.Servicegroup() sg.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name)) # Adding all attributes to allow any to be added if needed sg.servicegroup_name = target_servicegroup_name sg.alias = target_alias sg.members = target_members sg.servicegroup_members = target_servicegroup_members sg.notes = target_notes sg.notes_url = target_notes_url sg.action_url = '/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name) # Save sg.save() print "service group added" try: current_file = csv.reader(open(input_file, "rb"), delimiter='\t') except: logging.error('No such file or directory. Please try again') else: for line in current_file: for row in current_file: target_hostgroup_name = row[3] target_alias = row[4] target_members = row[5] target_hostgroup_members = row[6] target_notes = row[7] target_notes_url = row[8] target_action_url = row[9] target_host_name = row[10] target_service_description = row[11] target_display_name = row[12] target_servicegroups = row[13] target_is_volatile = row[14] target_check_command = row[15] target_initial_state = row[16] target_max_check_attempts = row[17] target_check_interval = row[18] target_retry_interval = row[19] target_active_checks_enabled = row[20] target_passive_checks_enabled = row[21] target_check_period = row[22] target_obsess_over_service = row[23] target_check_freshness = row[24] target_freshness_threshold = row[25] target_event_handler = row[26] target_event_handler_enabled = row[27] target_low_flap_threshold = row[28] target_high_flap_threshold = row[29] target_flap_detection_enabled = row[30] target_flap_detection_options = row[31] target_process_perf_data = row[32] target_retain_status_information = row[33] target_retain_nonstatus_information = row[34] target_notification_interval = row[35] target_first_notification_delay = row[36] target_notification_period = row[37] target_notification_options = row[38] target_notifications_enabled = row[39] target_contacts = row[40] target_contact_groups = row[41] target_stalking_options = row[42] target_icon_image = row[43] target_icon_image_alt = row[44] target_servicegroup_name = row[45] target_servicegroup_members = row[46]
If the values are in the same order every time, you could consider populating a list that you then could loop over, instead of doing it one by one. For the "target" portion of your script, you could nest another loop for range(3, 46) as well, and pass the index to your list instead of manually for every number from 3 to 46.
Why do you do this? for line in current_file: for row in current_file: If the first row is a header row and you're skipping it on purpose, you can use a DictReader instead. It doesn't look like you'll be able to do much to clean this up, but you could factor out each "section" into its own function: def save_hostgroup(name, alias, members, hostgroup_members, notes, notes_url, action_url): hg = Model.Hostgroup() hg.set_filename('/etc/nagios/objects/solution1/{0}.cfg'.format(target_hostgroup_name)) # Adding all attributes to allow any to be added if needed hg.hostgroup_name = target_hostgroup_name hg.alias = target_alias hg.members = target_members hg.hostgroup_members = target_hostgroup_members hg.notes = target_notes hg.notes_url = target_notes_url hg.action_url = target_action_url hg.save()
Behind the scenes all the member names of an object are stored in a dict. You can access this dict with vars(obj) or obj.__dict__. You can then use the update method of the dict to add a set of names to your object. eg. class SomeClass: def __str__(self): return "SomeClass({})".format( ", ".join( "{}={!r}".format(key, value) for key, value in self.__dict__.items() ) ) __repr__ = __str__ target_names = ['var_a', 'var_b', 'var_c'] target_values = [1, 2, 3] target = dict(zip(target_names, target_values)) assert target == {'var_a': 1, 'var_b': 2, 'var_c': 3} s = SomeClass() vars(s).update(target) assert hasattr(s, 'var_a') assert s.var_a == 1 print(s) # prints SomeClass(var_c=3, var_a=1, var_b=2)
Does Python 3 have LDAP module?
I am porting some Java code to Python and we would like to use Python 3 but I can't find LDAP module for Python 3 in Windows. This is forcing us to use 2.6 version and it is bothersome as rest of the code is already in 3.0 format.
You may use ldap3 module (formerly known as python3-ldap), it runs on python3 really well and requires no external C dependances. Also it can correctly handle both unicode and byte data in ldap records (in early versions there was a trouble with jpegPhoto field, now everything is fine)
If you're running this on Windows, you can get LDAP to work in Python 3.1 by using the ADO access method via Mark Hammond's PyWin32. To test this, I installed ActiveState Python 3.1, then installed PyWin32 for Python 3.1 http://sourceforge.net/projects/pywin32/files/ I was then able to run LDAP queries using a module I wrote that is based on this LDAP code from the ActiveState Python Cookbook: Recipe 511451: Dump all Active Directory Information using LDAP scripting by Manuel Garcia http://code.activestate.com/recipes/511451/ although now that I look at it I realize I completely rewrote my module just using his code as an example. Update Here is my LDAPList module and another support module to convert user access bit codes into something a tiny bit more english-like: LDAPList.py # LDAPList.py # Todd Fiske # class to encapsulate accessing LDAP information # 2009-03-18 first version # 2010-01-04 updated for Python 3 (print functions, <> to !=) import win32com.client import UACCodes ADS_SCOPE_SUBTREE = 2 class LDAPList(): def __init__(self, sContext): self.Context = sContext # naming context, "DC=xyz,DC=org" self.objectCategory = "" self.objectClass = "" self.FilterClause = "" self.query = "" self.cn = None self.cm = None self.rs = None def SetCategory(self, sCategory): self.objectCategory = sCategory self.FilterClause = "where objectCategory = '%s'" % self.objectCategory def SetClass(self, sClass): self.objectClass = sClass self.FilterClause = "where objectClass = '%s'" % self.objectClass def open(self): self.query = "select * from 'LDAP://%s' %s order by displayName" % (self.Context, self.FilterClause) self.cn = win32com.client.Dispatch("ADODB.Connection") self.cm = win32com.client.Dispatch("ADODB.Command") self.cn.Open("Provider=ADsDSOObject") self.cm.ActiveConnection = self.cn self.cm.Properties["Page Size"] = 1000 self.cm.Properties["Searchscope"] = ADS_SCOPE_SUBTREE self.cm.CommandText = self.query self.rs = self.cm.Execute()[0] def close(self): if self.rs is not None: self.rs.Close() self.rs = None if self.cm is not None: self.cm = None if self.cn is not None: self.cn.Close() self.cn = None def count(self): if self.rs is None: return -2 return self.rs.RecordCount def more(self): if self.rs is None: return False return not self.rs.EOF def GetObject(self): if self.rs is None: return None return win32com.client.GetObject(self.rs.Fields["ADsPath"].Value) def next(self): if self.rs is None: return self.rs.MoveNext() #---------- # helper functions def NamingContext(): # return default naming context root = win32com.client.GetObject("LDAP://RootDse") return root.get("DefaultNamingContext") def AccountControl(obj): if obj.userAccountControl is not None: return obj.userAccountControl else: return 0 def ConvertUAC(nUAC): return UACCodes.ConvertUAC(nUAC) def AccountActive(n): return (n & UACCodes.ADS_UF_ACCOUNTDISABLE) != UACCodes.ADS_UF_ACCOUNTDISABLE def GetCategory(obj): # CN=Group,CN=Schema,CN=Configuration,DC=xyz,DC=org s = obj.objectCategory s = s.split(",")[0][3:] return s # s = "Group" def GetGroups(obj): """ ('CN=XYZ Staff Rockville,OU=Distribution Groups,DC=xyz,DC=org', 'CN=XYZ Staff,OU=Distribution Groups,DC=xyz,DC=org') """ if obj.memberOf is None: return "" if type(obj.memberOf)==type(()): tGroups = obj.memberOf else: tGroups = (obj.memberOf,) return tGroups def GetNameParts(obj): if obj.givenName is None: sFirst = "" else: sFirst = obj.givenName if obj.middleName is None: sMiddle = "" else: sMiddle = obj.middleName if obj.sn is None: sLast = "" else: sLast = obj.sn if sLast == "" and sFirst == "": if obj.name is not None: sName = obj.name sName = sName[3:] lParts = sName.split(" ") if len(lParts) == 1: "todo: split on embedded capital letter" print("single-part name: %s" % sName) sFirst = sName else: sLast = lParts[-1] sFirst = " ".join(lParts[:-1]) return (sFirst, sMiddle, sLast) def GetManager(obj): if obj.manager is None: return "" else: return obj.manager #---------- # test if __name__ == "__main__": print print("testing LDAPList class") nc = NamingContext() print("context =", nc) ll = LDAPList(nc) ll.SetCategory('user') ll.open() # generates recordset print("query = %s" % ll.query) print("%d items" % ll.count()) n = 0 while (n < 10) and (ll.more()): o = ll.GetObject() # return nUAC = AccountControl(o) print("%-30s %-30s %-30s %-40s %s" % ( o.displayName, o.name, o.sAMAccountName, UACCodes.ConvertUAC(nUAC), GetManager(o) )) n += 1 ll.next() ll.close() ### UACCodes.py # UACCodes.py # Todd Fiske # generated 2009-09-23 16:36:56 by BuildUACCodes.py # updated 2010-01-04 for Python 3 (print functions) # provide UAC constants, lookup list, and conversion function import sys # UAC Constants ADS_UF_SCRIPT = 0x00000001 ADS_UF_ACCOUNTDISABLE = 0x00000002 ADS_UF_HOMEDIR_REQUIRED = 0x00000008 ADS_UF_LOCKOUT = 0x00000010 ADS_UF_PASSWD_NOTREQD = 0x00000020 ADS_UF_PASSWD_CANT_CHANGE = 0x00000040 ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x00000080 ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0x00000100 ADS_UF_NORMAL_ACCOUNT = 0x00000200 ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0x00000800 ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x00001000 ADS_UF_SERVER_TRUST_ACCOUNT = 0x00002000 ADS_UF_DONT_EXPIRE_PASSWD = 0x00010000 ADS_UF_MNS_LOGON_ACCOUNT = 0x00020000 ADS_UF_SMARTCARD_REQUIRED = 0x00040000 ADS_UF_TRUSTED_FOR_DELEGATION = 0x00080000 ADS_UF_NOT_DELEGATED = 0x00100000 ADS_UF_USE_DES_KEY_ONLY = 0x00200000 ADS_UF_DONT_REQUIRE_PREAUTH = 0x00400000 ADS_UF_PASSWORD_EXPIRED = 0x00800000 ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x01000000 # UAC short name lookup list lUACCodes = [ ("ADS_UF_SCRIPT" , 0x00000001, "script"), ("ADS_UF_ACCOUNTDISABLE" , 0x00000002, "disabled"), ("ADS_UF_HOMEDIR_REQUIRED" , 0x00000008, "homedir"), ("ADS_UF_LOCKOUT" , 0x00000010, "lockout"), ("ADS_UF_PASSWD_NOTREQD" , 0x00000020, "pwnotreqd"), ("ADS_UF_PASSWD_CANT_CHANGE" , 0x00000040, "pwcantchange"), ("ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED" , 0x00000080, "encryptedpw"), ("ADS_UF_TEMP_DUPLICATE_ACCOUNT" , 0x00000100, "dupaccount"), ("ADS_UF_NORMAL_ACCOUNT" , 0x00000200, "useracct"), ("ADS_UF_INTERDOMAIN_TRUST_ACCOUNT" , 0x00000800, "interdomain"), ("ADS_UF_WORKSTATION_TRUST_ACCOUNT" , 0x00001000, "workstation"), ("ADS_UF_SERVER_TRUST_ACCOUNT" , 0x00002000, "server"), ("ADS_UF_DONT_EXPIRE_PASSWD" , 0x00010000, "pwnoexpire"), ("ADS_UF_MNS_LOGON_ACCOUNT" , 0x00020000, "mnslogon"), ("ADS_UF_SMARTCARD_REQUIRED" , 0x00040000, "smartcard"), ("ADS_UF_TRUSTED_FOR_DELEGATION" , 0x00080000, "trustdeleg"), ("ADS_UF_NOT_DELEGATED" , 0x00100000, "notdeleg"), ("ADS_UF_USE_DES_KEY_ONLY" , 0x00200000, "deskey"), ("ADS_UF_DONT_REQUIRE_PREAUTH" , 0x00400000, "nopreauth"), ("ADS_UF_PASSWORD_EXPIRED" , 0x00800000, "pwexpired"), ("ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION", 0x01000000, "trustauth"), ] # UAC conversion function def ConvertUAC(nUAC): s = "" for c in lUACCodes: if ((nUAC & c[1]) == c[1]): s = s + c[2] + " " return s # test routine if __name__ == "__main__": print("UACCodes Test") print("-------------") for n in [0, 512, 514, 65535]: print("%d = %s" % (n, ConvertUAC(n))) print for s in sys.argv[1:]: n = int(s) print("%d = %s" % (n, ConvertUAC(n))) ### Both modules have some usage examples and should be fairly easy to figure out, but let me know if you have any questions or comments.
There is a Pure Python implementation of an LDAP client called Ldaptor. I don't think it's maintained though. If you really need it, you might be able to run 2to3 on this and port it.
This answer is no longer accurate; see below for other answers. Sorry to break this on you, but I don't think there is a python-ldap for Python 3 (yet)... That's the reason why we should keep active development at Python 2.6 for now (as long as most crucial dependencies (libs) are not ported to 3.0).