Getting the data updated with pymongo while pprint does not work - python-3.x

I have the same issue about getting the data updated with pymongo
How to get the data updated with pymongo
But pprint() cannot solve my problem.
Environment: Python, MongoDB, Pymongo
I'm getting "x" as my recent update value, just like getting the "results" in previous link, that why I'm wondering the same solution isn't fit, my x is <pymongo.results.UpdateResult object at 0x00000216021EA080>
print(x)
print(type(x))
<pymongo.results.UpdateResult object at 0x00000216021EA080>
<class 'pymongo.results.UpdateResult'>
Here is the code:
import pymongo
import datetime
import json
from pprint import pprint
def init_db(ip, db, coll):
myclient = pymongo.MongoClient('mongodb://' + ip + '/')
mydb = myclient[db]
mycol = mydb[coll]
return mydb, mycol
def change_db_data(myquery_json, one_or_many_bool, newvalues_json ):
if one_or_many_bool == True:
x = mycol.products.update_many(myquery_json, newvalues_json)
else:
x = mycol.products.update_one(myquery_json, newvalues_json)
return x
ip_input = input("Enter the ip: ")
exist_DB_name = input("Enter exist DB name: ")
exist_coll_name = input("Enter exist collection name: ")
mydb, mycol = init_db(ip_input, exist_DB_name, exist_coll_name)
myquery_str = input("Enter ur query: ")
update_one_or_many = input("U are update one or many values? (ex:1 for many , 0 for one): ")
newvalues_str = input("Enter new values: ")
one_or_many_bool = bool(int(update_one_or_many))
myquery_json =json.loads(myquery_str)
newvalues_json =json.loads(newvalues_str)
x = change_db_data(myquery_json, one_or_many_bool, newvalues_json)
print(x)
print(type(x))
pprint(x)
pprint(type(x))
The output
Enter the ip: localhost:27017
Enter exist DB name: (practice_10_14)-0002
Enter exist collection name: collection_new02cp
Enter ur query: { "name": { "$regex": "^R" }, "Age" : { "$gt": 50 } }
U are update one or many values? (ex:1 for many , 0 for one): 1
Enter new values: { "$set": { "name": "Old Mr.R" }}
<pymongo.results.UpdateResult object at 0x00000216021EA080>
<class 'pymongo.results.UpdateResult'>
<pymongo.results.UpdateResult object at 0x00000216021EA080>
<class 'pymongo.results.UpdateResult'>
My print(x) and pprint(x) print the same value, which pprint() isn't work.
I want it print out the modify data

But pprint() cannot solve my problem.
The pprint() method is not the solution in the question that you linked. Both that question and the answer use pprint(), so that method is not the problem itself. Rather, the problem in that question is that they were attempting to pprint() the wrong thing. That's the same thing that is happening here.
The answer to that question was to print something other than the object returned directly from the method. Currently, PyMongo returns an UpdateResult object for those update methods. Python doesn't know how to print this object directly:
>>> print(x)
<pymongo.results.UpdateResult object at 0x7fe842511df0>
But you can print its properties:
>>> print(x.modified_count)
1
It also includes a raw_result property which might be what you are interested in:
>>> print(x.raw_result)
{'n': 1, 'nModified': 1, 'ok': 1.0, 'updatedExisting': True}
This all works the exact same with pprint():
>>> pprint(x)
<pymongo.results.UpdateResult object at 0x7fe842511df0>
>>> pprint(x.modified_count)
1
>>> pprint(x.raw_result)
{'n': 1, 'nModified': 1, 'ok': 1.0, 'updatedExisting': True}
Finally, I think you may have copied the code from the other question too directly. Both of your update statements have the following:
... mycol.products.update ...
But products is the name of the collection from the other question. In that other question they are performing db.products.update where they are starting with the database (db) itself. But in your code you have already established the collection object as a variable (mycol = mydb[coll]). And you are attempting to use mycol when doing the update. So your updates should probably drop the reference to products and be something like:
... mycol.update ...

Related

Modifying a nested dictionary

I'm using regex to look through a file to check for a username and whether their action caused an error or not (ERROR for error, INFO for successful action)
I am using a nested dictionary to keep track of actions, with the username as the primary key and the nested dictionary of how many INFO and ERROR lines they generate.
#!/usr/bin/env python3
import re
users = {}
with open('logfile.txt') as f:
for line in f:
regex_user = r"(INFO|ERROR): .* \((.+)\)$"
"""searches for users and if there message was info or error"""
user = re.serach(regex_user, line)
if user is None:
continue
name = user[2]
cat = user[1]
try:
# Method 1?
users[name][cat] = users[name].get(cat, 0) + 1
# Method 2?
users[name][cat] = users.get(name, {}).get(cat, 0) + 1
except KeyError:
print("Where are my keys?")
I am wondering which of the two methods (if any) are correctly modifying the dictionary to increase the count of the respective nested key.
Output should look like:
{'John': {'INFO': 22, 'ERROR': 3}}
if the log contained 22 lines of INFO and 3 lines of ERROR for user John.
You probably want to solve this with a nested collections.defaultdict or alternatively using setdefault() though the latter is not a clean in my opinion. collections.defaultdict() will allow you to reference a dictionary key that does not yet exist which is the crux of your issue.
Try something like:
import collections
import json
import random
users = collections.defaultdict(lambda: collections.defaultdict(int))
for i in range(100):
user = random.choice(["John", "Jane", "Sanjay"])
cat = random.choice(["INFO", "ERROR"])
users[user][cat] += 1
print(json.dumps(users, indent=2))
That will print out something like:
{
"Jane": {
"INFO": 16,
"ERROR": 19
},
"John": {
"ERROR": 21,
"INFO": 10
},
"Sanjay": {
"INFO": 18,
"ERROR": 16
}
}
though each run will be different.
As we noted by #Ryukashin, a defaultdict() does not print() as nicely as a dict(). So casting back is possilbe if it is really needed for some reason. The easiest (no not the most efficient) manner for that might be:
users = json.loads(json.dumps(users))

How to create a program that allows me to answer questions and add the values to the dictionary until I tell it to stop and encrypt it?

I am trying to create a program that allows a user to add each answer to a dict. I am also trying to repeat the process until asked to stop. I am trying to create multiple dicts and then encrypt them.
Should I create a dict inside a list to create multiple dicts and how can I validate the information before adding it to the dict.
import base64
from datetime import datetime
from cryptography.fernet import Fernet
import pickle
from base64 import b64decode
def username():
try:
while True:
name = [" ", "-"]
names = input("Enter Name:")
for n in name:
if n in str(names):
break
if str(names):
break
except TypeError:
print('wrong')
return names
def userDOB():
try:
dob = input("Enter your date of birth - MM/DD/XXXX:")
date = datetime.strptime(dob, '%m/%d/%Y')
if date:
print(f' {date.month}/{date.day}/{date.year}')
except ValueError:
while True:
print("Please Enter Date Of Birth - MM/DD/XXXX")
dob = input("MM/DD/XXXX:")
date = datetime.strptime(dob, '%m/%d/%Y')
if date:
break
return dob
def userstraddress():
stradd = [" ", " . "]
straddress = input("Enter The Street Address:")
for x in stradd:
if x in straddress:
return straddress
def useremail():
email = ["#", "."]
emailaddress = input("Enter Email Address:")
for n in email:
if n in emailaddress:
try:
emails = str(emailaddress)
if emails:
break
except TypeError:
print("Error")
return emailaddress
x = {'Name': " ", 'Date of Birth': " ", 'Street Address':" ", 'Email Address': " "}
x.update({'Name':username()})
x.update({'Date of Birth': userDOB()})
x.update({'Street Address': userstraddress()})
x.update({'Email Address': useremail()})
xx = str(x).encode('utf-8')
base64_dict = base64.b64encode(xx)
print(base64_dict)
xx1 = eval(base64.b64decode(base64_dict))
print(xx)
This code doesn't look good. Typically first you get the raw_data. Then you sanitise data and run validation checks on it as well. The validation logic looks doesn't look like it would work properly. Do not put loop in the except block. The except block is to handle exception, like logging or displaying it or doing something else. An infinite loop in exception block is bad code.
Get the data in a single loop. If data isn't entered properly in that loop, let it fail. Save the entered data into a dictionary or list. Run validation as appropriate for each field as per your requirement. If you need a good and easy data model and validation library check out Pydantic. You can also check validation examples provided there.
https://pydantic-docs.helpmanual.io/

Combining Optional Passed query filters in Peewee

I am trying to Link a flask server to a Peewee database. I have a Rest GET request that passes data of the form
{'a':1,'b':2, 'filter':{'name':'Foo', 'count':3}}
I want to write a method that converts my filters into a database query and execute it to return their resource:
import datetime
import peewee as pw
import uuid
DATABASE = "Resources.db"
database = pw.SqliteDatabase(DATABASE)
class BaseModel(pw.Model):
class Meta:
database = database
class Resource(BaseModel):
name = pw.CharField(unique=True)
current_count = pw.IntegerField(default=1)
total_count = pw.IntegerField(default=1)
flavor = pw.CharField(default="undefined")
users = pw.TextField()
metadata = pw.TextField(default="")
is_avalible = pw.BooleanField(default=True)
uuid = pw.UUIDField(primary_key=True, default=uuid.uuid4)
max_reservation_time = pw.IntegerField(default=10)
def __str__(self):
return f"My name is {self.name} {vars(self)}"
This is kinda what my resource looks like. Here is what I am trying to do... (not a working full example)
def filter(filters):
for i,j in filters.items():
dq = Resource.select().where(getattr(Resource, i) == j)
for resource in dq:
print(resource)
if __name__ == "__main__":
try:
database.connect()
except pw.OperationalError:
print("Open Connection")
try:
create_tables()
except pw.OperationalError:
print("Resource table already exists!")
with database.atomic():
reso = Resource.create(name="Burns", current_count=4, total_count=5, users="Bar", blah=2)
filter({'name':"Burns","total_count":5})
Here I would expect to get back: My name is Burns {'__data__': {'uuid': UUID('80808e3a-4b10-47a5-9d4f-ff9ff9ca6f5c'), 'name': 'Burns', 'current_count': 4, 'total_count': 5, 'flavor': 'undefined', 'users': 'Grant', 'metadata': '', 'is_avalible': True, 'max_reservation_time': 10}, '_dirty': set(), '__rel__': {}}I believe I might be able to create individual peewee.expressions and join them some how, I just am not sure how.
Since peewee expressions can be arbitrarily combined using the builtin & and | operators, we'll use the reduce() function to combine the list using the given operand:
def filter(filters):
expression_list = [getattr(Resource, field) == value
for field, value in filters.items()]
# To combine all expressions with "AND":
anded_expr = reduce(operator.and_, expression_list)
# To combine all expressions with "OR":
ored_expr = reduce(operator.or_, expression_list)
# Then:
return Resource.select().where(anded_expr) # or, ored_expr
Thanks to #coleifer for the reminder. Here was my solution:
OP_MAP = {
"==": pw.OP.EQ,
"!=": pw.OP.NE,
">": pw.OP.GT,
"<": pw.OP.LT,
">=": pw.OP.GTE,
"<=": pw.OP.LTE,
}
def _generate_expressions(model, query_filter):
expressions = []
for expression in query_filter:
expressions.append(
pw.Expression(
getattr(model, expression["attr"]), OP_MAP[expression["op"]], expression["value"]
)
)
return expressions
def generate_query(model, query_data):
if query_data.get("filters") is None:
database_query = model.select()
else:
database_query = model.select().where(
*(_generate_expressions(model, query_data["filters"]))
)
return database_query
I pass the type of object I want to create an expression for and operator in the filter data. Iterating over the filters I can build the expressions and combine them.

Is it possible to return a bool from a unittest.TestCase?

I'm looking to log the results of testing in an excel file. This is my expected output
test, True, 2018/11/27 OR test, False, 2018/11/27
Currently, to achieve this, I have an incredibly cumbersome implimentation. Here's my Excel writer class
xlwriter.py
class XLWriter:
def __init__(self, file):
self.workbook = load_workbook(file)
self.worksheet = self.workbook['Sheet1']
self.file = file
def write_true(self, row):
index = 0
# function name, declare test passed, date
values = [inspect.stack()[1][3], True, datetime.date)]
# column numbers of above
columns = [4, 6, 8]
while index < 2:
cell = self.worksheet.cell(row=row, column=columns[index])
cell.value = values[index]
index += 1
def write_true(self, row):
index = 0
# function name, declare test passed, date
values = [inspect.stack()[1][3], False, datetime.date)]
# column numbers of above
columns = [4, 6, 8]
while index < 2:
cell = self.worksheet.cell(row=row, column=columns[index])
cell.value = values[index]
index += 1
And an example assertation from a test
test.py
try:
self.assertEqual(url, url)
xl.write_true(14)
xl.save()
except:
xl.write_false(14)
xl.save()
This is not scalable. I was thinking a quick fix would be to return a True or False bool dependent on whether or not the test was successful, but I don't see a function for that behaviour in the unittest docs.
Short answer - No.
Long answer - No. But.. There are ways around the problem.
To re-vist the problem three months later, what do we actually plan to achieve?
We want to do the following
Run a unittest
Tell our database the test ran successfully
There is no need to return anything from the test itself in this case. Rather than returning a boolean, we can instead send a notification to xlwriter.px with the information it needs.
Before we do that, we need to rewrite xlwriter.py. Since creating this script, I've ported the database to SQLite.
Manager.py
import sqlite3
import datetime
import os
class Manager:
def write_results_true(self, test):
connection = sqlite3.connect(os.path.abspath('path'))
connection.execute('UPDATE Details '
'SET Passed'
'= "True"'
'WHERE Name = "' + test + '";')
connection.commit()
connection.close()
def write_results_false(self, test):
connection = sqlite3.connect(os.path.abspath('path'))
connection.execute('UPDATE Details '
'SET Passed'
'= "False"'
'WHERE Name = "' + test + '";')
connection.commit()
connection.close()
We've simplified the manager class, and now, to write to our database it's simple.
test.py
def test_sample_test(self):
"""
A sample test
"""
a = 1
if a == 1:
m.write_results_true(stack()[0].function)
self.assertEqual(a, 1)
else:
m.write_results_false(stack()[0].function)
# A comment on why the test has failed
self.fail('a does not equals 1')

No such property: expected for class: Script1343 (in groovy script);

I am trying to retrieve data from oracle db but getting No such property: expected for class: Script1343 (in groovy script); error
import java.util.Properties;
import java.io.InputStream;
import groovy.sql.Sql;
def url = 'jdbc:oracle:thin:#//localhost:1521/TEST'
def user = 'DB'
def password = 'DB'
def driver = 'oracle.jdbc.driver.OracleDriver'
def sql = Sql.newInstance('url', 'User', 'password','oracle.jdbc.driver.OracleDriver')
sql.withStatement {
stmt -> stmt.queryTimeout = 30
print "Request TimeOut"
}
def rowNum = 0
sql.eachRow("SELECT DISTINCT CST_START_DT_PF,CST_ITEM_NUM_PF FROM COST "){ row ->
def first = row[0]
def middle = row.CST_START_DT_PF
def one = row.CST_ITEM_NUM_PF
assert expected[rowNum] == "$CST_START_DT_PF, $CST_ITEM_NUM_PF"
}
There are several things wrong. The specific error you asked about is the result of the following:
assert expected[rowNum] == "$CST_START_DT_PF, $CST_ITEM_NUM_PF"
You are referencing a variable expected which doesn't exist.
You didn't ask about the things below but other problems you are going to run into...
Referencing $CST_START_DT_PF and $CST_ITEM_NUM_PF is going to be a problem because they also don't exist, at least not in a way that your code will work.
You also are probably going to get unexpected results related to the fact that you are never incrementing rowNum.

Resources