Python Syntax Incorrect for Email Creation - python

I am trying to write out some basic python for my kolab email server. For the primary_mail, I want it to be first initial last name, such as jdoe. The default is first name (dot) last name. john.doe#domain.com
I have came up the following:
primary_mail ='%(givenname)s'[0:1]%(surname)s#%(domain)s
Which I want to basically say jdoe#domain.com
givenname would be someone's full name. (i.e John)
surname would be someone's last name. (i.e Doe)
domain is the email domain. domain.com
When python goes to canonify it, it comes up with some mumbo jumbo like so:
'john[0:1]'doe#domain.com
Can someone help me out with correcting this? I am so close.
EDIT:
According to kolab documentation, it looks like it is something like:
"{0}#{1}": "format('%(uid)s', '%(domain)s')"
This of course doesn't work for me though....
EDIT 2:
I am getting the following in my error logs:
imaps[1916]: ptload completely failed: unable to canonify identifier: 'john'[0:1]doe#domain.com

String formatting is by far the easiest, most readable and preferred way of accomplishing this:
first_name = 'John'
surname = 'Smith'
domain = 'company.com'
primary_mail = '{initial}{surname}#{domain}'.format(initial=first_name[0].lower(), surname=surname.lower(), domain=domain)
primary_mail now equals 'jsmith#company.com'. You define a string containing named placeholders in braces, then call the format method to have those placeholders replaced at runtime with the appropriate values. Here, we take the first character of first_name and convert it to lower case, convert the entirety of surname also, and leave domain unchanged.
You can read more on string formatting at the Python 2.7 docs.

James Scholes is right that format is a better way of doing it, however reading the Kolab documentation it seems that you can only give the format string, and they use the % style formatter internally, where you can't change it. From
the Kolab 'primary_mail' documentation
primary_mail = %(givenname)s.%(surname)s#%(domain)s
The equivalent of the following Python is then executed:
primary_mail = "%(givenname)s.%(surname)s#%(domain)s" % {
"givenname": "Maria",
"surname": "Moller",
"preferredlanguage": "en_US"
}
In this case, we need a modifier to the format conversation. We have %(givenname)s, which ensures that givenname is a string. We can also specify a minimum length, followed by a . and then a precision. This is normally only used it numbers, but we can use it for strings, too. Here is a format string with no minimum length, but a maximum length (precision) of 1 character:
"%(givenname).1s"
So you probably want a string like this:
"%(givenname).1s%(surname)#%(domain)"

Related

Does "in" do the same thing as str.contains()?

I'm new to Python but am very confused as to how this code works:
Correct code I don't understand:
I don't understand how in the function, you can just write ".org' in domain to capture whether the referrer_domain is an organization. I thought you would have to filter via .str.contains() to be able to see if the domain includes .org or .com.
I originally coded:
dot_org = data[data['referrer_domain'].str.contains('.org')
dot_com = data[data['referrer_domain'].str.contains('.com')
def domain_type(type):
if type in dot_org['referrer_domain']:
return 'organization'
elif type in dot_com['referrer_domain']:
return 'company'
else:
return 'other'
data['new_column'] = data['referrer_domain'].apply(domain_type)
But this ended up labeling all of the rows in the new column I created as "other".
Is anyone able to explain why the code in the picture works, but why the code above doesn't?
First, you should not use type as a variable name, because it's a reserved word.
Aside from that, there is no str.contains method, at least not in plain Python. The official way of checking if a string contains another string is using the in operator.

Turning x.x.x.x string into list address (???)

This is a difficult problem to explain. I have a string that looks like "system.cpu.total.pct" that I'm pulling from a json configuration file. This particular format is required elsewhere in my program so I cannot change it.
This "system.cpu.total.pct" specifies what field I'm interested in snagging out of metricbeat (in Elasticsearch).
I need to convert this into a list address (? is that what to call it ?) so that I can snag stuff out of an array of database results I'm calling 'rawData'. Right now I'm doing this:
if sourceSet == "system.cpu.total.pct":
dataArray.append(rawData['hits']['hits'][thisRecord]["_source"]['system']['cpu']['total']['pct'])
But that's no good, obviously, because the result is hard-coded.
How can I instead write something like
dataArray.append(rawData['hits']['hits'][thisRecord]["_source"]["system.cpu.total.pct"])
that will work for any arbitrary string?
Any suggestions? Thank you!
you can use:
if sourceSet == "system.cpu.total.pct":
d = rawData['hits']['hits'][thisRecord]["_source"]
for t in sourceSet.split('.'):
d = d[t]
dataArray.append(d)

How can I use f-string with a variable, not with a string literal?

I want to use f-string with my string variable, not with string defined with a string literal, "...".
Here is my code:
name=["deep","mahesh","nirbhay"]
user_input = r"certi_{element}" # this string I ask from user
for element in name:
print(f"{user_input}")
This code gives output:
certi_{element}
certi_{element}
certi_{element}
But I want:
certi_{deep}
certi_{mahesh}
certi_{nirbhay}
How can I do this?
f"..." strings are great when interpolating expression results into a literal, but you don't have a literal, you have a template string in a separate variable.
You can use str.format() to apply values to that template:
name=["deep","mahesh","nirbhay"]
user_input = "certi_{element}" # this string i ask from user
for value in name:
print(user_input.format(element=value))
String formatting placeholders that use names (such as {element}) are not variables. You assign a value for each name in the keyword arguments of the str.format() call instead. In the above example, element=value passes in the value of the value variable to fill in the placeholder with the element.
Unlike f-strings, the {...} placeholders are not expressions and you can't use arbitrary Python expressions in the template. This is a good thing, you wouldn't want end-users to be able to execute arbitrary Python code in your program. See the Format String Syntax documenation for details.
You can pass in any number of names; the string template doesn't have to use any of them. If you combine str.format() with the **mapping call convention, you can use any dictionary as the source of values:
template_values = {
'name': 'Ford Prefect',
'number': 42,
'company': 'Sirius Cybernetics Corporation',
'element': 'Improbability Drive',
}
print(user_input.format(**template_values)
The above would let a user use any of the names in template_values in their template, any number of times they like.
While you can use locals() and globals() to produce dictionaries mapping variable names to values, I'd not recommend that approach. Use a dedicated namespace like the above to limit what names are available, and document those names for your end-users.
If you define:
def fstr(template):
return eval(f"f'{template}'")
Then you can do:
name=["deep","mahesh","nirbhay"]
user_input = r"certi_{element}" # this string i ask from user
for element in name:
print(fstr(user_input))
Which gives as output:
certi_deep
certi_mahesh
certi_nirbhay
But be aware that users can use expressions in the template, like e.g.:
import os # assume you have used os somewhere
user_input = r"certi_{os.environ}"
for element in name:
print(fstr(user_input))
You definitely don't want this!
Therefore, a much safer option is to define:
def fstr(template, **kwargs):
return eval(f"f'{template}'", kwargs)
Arbitrary code is no longer possible, but users can still use string expressions like:
user_input = r"certi_{element.upper()*2}"
for element in name:
print(fstr(user_input, element=element))
Gives as output:
certi_DEEPDEEP
certi_MAHESHMAHESH
certi_NIRBHAYNIRBHAY
Which may be desired in some cases.
If you want the user to have access to your namespace, you can do that, but the consequences are entirely on you. Instead of using f-strings, you can use the format method to interpolate dynamically, with a very similar syntax.
If you want the user to have access to only a small number of specific variables, you can do something like
name=["deep", "mahesh", "nirbhay"]
user_input = "certi_{element}" # this string i ask from user
for element in name:
my_str = user_input.format(element=element)
print(f"{my_str}")
You can of course rename the key that the user inputs vs the variable name that you use:
my_str = user_input.format(element=some_other_variable)
And you can just go and let the user have access to your whole namespace (or at least most of it). Please don't do this, but be aware that you can:
my_str = user_input.format(**locals(), **globals())
The reason that I went with print(f'{my_str}') instead of print(my_str) is to avoid the situation where literal braces get treated as further, erroneous expansions. For example, user_input = 'certi_{{{element}}}'
I was looking for something similar with your problem.
I came across this other question's answer: https://stackoverflow.com/a/54780825/7381826
Using that idea, I tweaked your code:
user_input = r"certi_"
for element in name:
print(f"{user_input}{element}")
And I got this result:
certi_deep
certi_mahesh
certi_nirbhay
If you would rather stick to the layout in the question, then this final edit did the trick:
for element in name:
print(f"{user_input}" "{" f"{element}" "}")
Reading the security concerns of all other questions, I don't think this alternative has serious security risks because it does not define a new function with eval().
I am no security expert so please do correct me if I am wrong.
This is what you’re looking for. Just change the last line of your original code:
name=["deep","mahesh","nirbhay"]
user_input = "certi_{element}" # this string I ask from user
for element in name:
print(eval("f'" + f"{user_input}" + "'"))

What data type single element extracted from entries attribute of Connection object represent in python?

I am not well versed at python at all. I was asked to review someone else's python script that uses search ldap entries. Btw - I can't reach out to original developer for some reason and before it is deployed + tested visual code checking is required. With that constraints in mind, allow me to proceed.
import ldap3
from ldap3 import Server,Connection, ALL
conn = Connection(....)
conn.search(....)
for entry in conn.entries:
if (len(entry['cn']) > 0):
....
name = entry['name']
if name:
user_name = str(name)
else:
user_name = "Bob"
First question is len(entry['cn']) > 0 I like to interpret it as checking the length of characters of returned cn value from ldap e.g. cn=bob,ou=people,ou=foocomany. I am pretty sure entry['cn'] is NOT string type but I don't know what data type it represents. Can you tell me what type it is?
My 2nd + 3rd questions are not directly related to the original question, but plz bear with me asking for them with grace.
My 2nd question is, if that assumption is correct, entry['cn'] should be converted to string type like str(entry['cn']). Then check its length?
My 3rd question is on if stmt. I like to interpret it as if name is not null or if name is not None in pythonic way. Did I interpret it correctly? If so I should replace it as if not (name is None) would work? I googled on it to get that stmt.
Given the context and code provided, it looks like this snippet is using the ldap3 library.
From the relevant documentation, conn.entries should be a list of Entry objects.
This means that entry['cn'] should be returning an Attribute. Doing a bit of source diving, this appears to just be a fancy list with writable flags. len(entry['cn']) > 0 ends up calling this method, which just returns the number of values that attribute has. It being greater than 0 just ensuring that the cn is, in fact, set.

SOQL Socrata query datetime between

May I know what is wrong with my below code ? I would like to query all where date_occ is between '2015-01-10T12:00:00' and '2015-12-31T24:00:00'
response = requests.get('https://data.lacity.org/api/id/7fvc-faax.json?$select=*&$where = date_occ between 2015-01-10T12:00:00 and 2015-12-131T24:00:00')
I get the following error:
Unrecognized arguments [$where ]
I realise the following doesn't work as well
response = requests.get('https://data.lacity.org/api/id/7fvc-faax.json?$select=*&vict_age >20')
data = response.json()
data = json_normalize(data)
data = pd.DataFrame(data)
But this works:
response = requests.get('https://data.lacity.org/api/id/7fvc-faax.json?$select=*&vict_sex=M')
what am I missing here?
There are a few questions and answers posed in this one. Starting with your second query first; where you want to look at age above 20 years-old. Looking at the metadata (click the down arrow), the victim age is not numeric and is a text string. Thus, you won't be able to use operators like greater than, less than, etc. However, you can look for "equal to". The query below will work:
https://data.lacity.org/resource/7fvc-faax.json?$where=vict_age = '20'
Note: I've dropped the $select and am just using $where for simpler display.
Your third example works since you've set it to query a text field. If you want LA to change it to a numeric, click the "Contact Dataset Owner" under the ellipsis button.
Your first question on dates has a few changes. First, your single quotation marks were not aligned and some were missing. Second, the latter date is 2015-12-131T24:00:00, which has an invalid day. Finally, the data on the portal does not have a timestamp, so you only need the year-month-day. This will work:
https://data.lacity.org/resource/7fvc-faax.json?$where=date_occ between '2015-01-10' and '2015-12-13'
Finally, I would recommend that you use the URL structure, https://data.lacity.org/resource/7fvc-faax.json? instead of /api/id/. The former is the proper URL structure for Socrata-based APIs.

Categories

Resources