jsonpickle subclass of OrderedDict not working - python-3.4

What I am doing wrong:
class A(collections.OrderedDict):
def __init__(self,*largs,**kwargs):
super(A,self).__init__(*largs,**kwargs);
def __reduce__(self):
return super(A,self).__reduce__()
dt = collections.OrderedDict([(1,3),(34,2)]) # pickles fine
d=A([(1,3),(34,2)]) # pickles fine
js=pickle.dumps([d,dt])
print(js)
temp = pickle.loads(js)
print(temp)
# but it does not jsonpickle.decode ????
js=jsonpickle.encode(d)
print(js)
temp = jsonpickle.decode(js)
print(temp)

Obvisouly there is a special Handler which I should have registered for my class:
jsonpickle.handlers.register(A, handlers.OrderedDictReduceHandler)
then it works

Related

Streamlit session state and button

Does anyone know how the code below could be changed so that the print only happens when the button “Run” is clicked? Now the print is performed every time “inp” is changed.
import streamlit as st
inp = st.number_input(“inp”, min_value=0, max_value=10, step=1, value=10)
if ‘click’ not in st.session_state:
st.session_state.click = False
def onClickFunction():
st.session_state.click = True
st.session_state.out = inp
runButton = st.button(“Run”,
on_click=onClickFunction())
if st.session_state.click:
st.write(“out”, st.session_state.out)
Solution: remove the “()” after the onClickFunction.

Control display of an ipyvuetify page by a dropdown works in notebook not in voila

I have encountered another working in notebook but not in voila issue. I have tried for a couple of hours but feel like I am still missing something and therefore seeking expert opinions here.
I have a function create_pages_and_run() that takes in a dictionary, d, as an input to generate a dashboard (the data type is ipyvuetify.generated.App.App). The dictionary can be retrieved from a json file scenario_dict using a country name as key where I designed a dropdown to collect the country name.
The purpose is to ask user to select a country name and the page will be redrawn/refreshed. I have the following code that works in notebook but not in Voila. (Works means that when a new country name is selected, the dashboard is displayed with the widgets using data from that countries)
scenario_dropdown = widgets.Dropdown(
options=all_scenarios,
value=initial_scenario,
description="Scenario",
layout=widgets.Layout(margin="0 20px 0 0", height="39px", width="15%"),
)
d = scenario_dict[initial_scenario]
app = create_pages_and_run(d)
#the below code works for notebook
def on_change(change):
global d, app
if change["name"] == "value" and (change["new"] != change["old"]):
d = scenario_dict[change["new"]]
app = create_pages_and_run(d)
clear_output()
display(app)
scenario_dropdown.observe(on_change)
My failed code using ipywidgets.Output is as below. (Failed in the sense, after selecting country name in the dropdown no change is observed).
scenario_dropdown = widgets.Dropdown(
options=all_scenarios,
value=initial_scenario,
description="Scenario",
layout=widgets.Layout(margin="0 20px 0 0", height="39px", width="15%"),
)
d = scenario_dict[initial_scenario]
app = create_pages_and_run(d)
out = widgets.Output()
with out:
display(app)
# the code works failed for voila
def on_change(change):
global d, app, out
if change["name"] == "value" and (change["new"] != change["old"]):
d = scenario_dict[change["new"]]
app = create_pages_and_run(d)
out.clear_output()
with out:
display(app)
display(out)
scenario_dropdown.observe(on_change)
I appreciate your help, thanks.
I'm not sure why your code didn't work. Maybe it was the use of globals which can be avoided. Could you provide a working example to test. Here is a working example based on your code that works in Voila.
import ipywidgets as widgets
all_scenarios = ['aa','bb','cc']
initial_scenario = all_scenarios[0]
scenario_dict = {}
scenario_dict['aa'] = 'do_this'
scenario_dict['bb'] = 'do_that'
scenario_dict['cc'] = 'do_what'
def create_pages_and_run(action):
print(action)
scenario_dropdown = widgets.Dropdown(
options=all_scenarios,
value=initial_scenario,
description="Scenario",
layout=widgets.Layout(margin="0 20px 0 0", height="39px", width="15%"),
)
d = scenario_dict[initial_scenario]
out = widgets.Output()
with out:
create_pages_and_run(d)
app = widgets.VBox([scenario_dropdown, out])
def on_change(change):
if change["name"] == "value" and (change["new"] != change["old"]):
d = scenario_dict[change["new"]]
out.clear_output()
with out:
create_pages_and_run(d)
scenario_dropdown.observe(on_change)
app

python re data structure

The dataset file in assets/grades.txt contains a line separated list of people with their grade in a class. Create a regex to generate a list of just those students who received a B in the course.
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
for line in grades:
line = line.rstrip()
if re.search('^X\S*: [0-9.]+', line):
print(line)
assert len(grades()) == 16
The easy solution is to add the following regular expression '([A-Z][a-z]+ [A-Z][a-z]+): B'.
this solution is provided from abd-elrhman-mohey
I can see where you did go wrong my friend
first of all
grades it's the lines u don't need the for loop to get them
second of all, I don't know why did u use '^X\S*: [0-9.]+' as it seems out of what u want
you need to see if the grades ar numbers or normal grades (A B C D)
and appears from the question that u need to get B
so we can say the final code will be
for the find
'([A-Z][a-z]+ [A-Z][a-z]+): B'
and final code I guess will be
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
w = '([A-Z][a-z]+ [A-Z][a-z]+): B'
grades = re.findall(w , grades)
return grades
import re
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
list_of_grades = grades.split('\n')
print(list_of_grades)
list_of_students = [ li.split()[0] + ' ' + li.split()[1] for li in list_of_grades if li.split()[-1] == 'B']
print(list_of_students)
return list_of_students
this works for me well as a piece of cake
import re
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
# YOUR CODE HERE
result = re.findall(': B', grades)
return result
grades()
len(grades())
This has worked well for me
import re
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
# YOUR CODE HERE
pattern=re.findall('([A-Za-z]+ [A-Za-z]+): B',grades)
return pattern
#raise NotImplementedError()
You can check by running the following code
assert len(grades()) == 16
To learn more about regex, visit: https://docs.python.org/3/library/re.html#module-re
This is what I did
import re
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
# YOUR CODE HERE
result = re.findall('\w* \w*: B',grades )
return result
print(grades())
#Here is my code:
` import re
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
a=re.findall("([\w ]*)(?=\:\sB)",grades)
return a
# YOUR CODE HERE
raise NotImplementedError()
#the output looks like a this:
#['Bell Kassulke',
'',
'Simon Loidl',
'',
'Elias Jovanovic',
'',
'Hakim Botros',
'',
'Emilie Lorentsen',#
i want the output to return only names and not the spaces.
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
pattern=re.findall("[\w ]*)(\:\ B)",grades)
return pattern
grades()
import re
def grades():
with open ("assets/grades.txt", "r") as file:
grades = file.read()
only_B_grades = re.findall("[A-Z][a-z]* [A-Z][a-z]*\: [B]",grades)
person = [grade_B.split(':')[0] for grade_B in only_B_grades]
return person
raise NotImplementedError()
grades()

I need help web scraping comments section

I am currently doing a project on football players. I am trying to scrape some public comments on football players for sentiment analysis. However I can't seem to scrape the comment. Any help would be MUCH appreciated. It is the comments part I can't seem to do. Weirdly enough I had it working but then it stopped and I cant seem to get scraping comments again. The website I am scraping from is : https://sofifa.com/player/192985/kevin-de-bruyne/200025/
likes = []
dislikes = []
follows = []
comments = []
driver_path = '/Users/niallmcnulty/Desktop/GeneralAssembly/Lessons/DSI11-lessons/week05/day2_web_scraping_and_apis/web_scraping/selenium-examples/chromedriver'
driver = webdriver.Chrome(executable_path=driver_path)
# i = 0
for url in tqdm_notebook(urls):
driver.get(url)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
sleep(0.2)
soup1 = BeautifulSoup(driver.page_source,'lxml')
try:
dislike = soup1.find('button', attrs = {'class':'bp3-button bp3-minimal bp3-intent-danger dislike-btn need-sign-in'}).find('span',{'class':'count'}).text.strip()
dislikes.append(dislike)
except:
pass
try:
like = soup1.find('button', attrs = {'class':'bp3-button bp3-minimal bp3-intent-success like-btn need-sign-in'}).find('span',{'class':'count'}).text.strip()
likes.append(like)
except:
pass
try:
follow = soup1.find('button', attrs = {'class':'bp3-button bp3-minimal follow-btn need-sign-in'}).find('span',{'class':'count'}).text.strip()
follows.append(follow)
except:
pass
try:
comment = soup1.find_all('p').text[0:10]
comments.append(comment)
except:
pass
# i += 1
# if i % 5 == 0:
# sentiment = pd.DataFrame({"dislikes":dislikes,"likes":likes,"follows":follows,"comments":comments})
# sentiment.to_csv('/Users/niallmcnulty/Desktop/GeneralAssembly/Lessons/DSI11-lessons/projects/cap-csv/sentiment.csv')
sentiment_final = pd.DataFrame({"dislikes":dislikes,"likes":likes,"follows":follows,"comments":comments})
# df_sent = pd.merge(df, sentiment, left_index=True, right_index=True)
The comments section is dynamically loaded. you can try to capture it using the driver,
try:
comment_elements = driver.find_elements_by_tag_name('p')
for comment in comment_elements:
comments.append(comment.text)
except:
pass
print(Comments)

Why does WTForms have unbound fields the first time the page is loaded?

I have the following form classes:
class FieldsRequiredForm(FlaskForm):
class Meta:
def render_field(self, field, render_kw):
render_kw.setdefault('required', True)
return super().render_field(field, render_kw)
class SingleStringFieldForm(FieldsRequiredForm):
def __init__(self, field_label=None, question_id=None,
submit_label='Submit'):
super().__init__()
SingleStringFieldForm.answer = StringField(field_label)
SingleStringFieldForm.question_id = HiddenField(default=question_id)
SingleStringFieldForm.submit = SubmitField(submit_label)
class SingleRadioFieldForm(FieldsRequiredForm):
def __init__(self, field_label=None, question_id=None,
submit_label='Submit', choices=None):
super().__init__()
SingleRadioFieldForm.answer = RadioField(field_label, choices=choices)
SingleRadioFieldForm.question_id = HiddenField(default=question_id)
SingleRadioFieldForm.submit = SubmitField(submit_label)
The function that's using these forms looks like this:
#bp.route('/survey/<string:slug>', methods=['GET', 'POST'])
def question(slug):
survey = Survey.query.filter_by(slug=slug).first_or_404()
questions = survey.questions
question_ids = [question.id for question in questions]
if 'answers' not in session:
session['answers'] = json.dumps({id: None for id in question_ids})
answers = json.loads(session['answers'])
if request.method == 'POST':
record_submitted_answer()
answers = json.loads(session['answers'])
if None in answers.values():
question = get_next_question()
if question.category == 'word':
form = SingleStringFieldForm(field_label=question.question,
question_id=question.id)
elif question.category == 'likert':
form = SingleRadioFieldForm(field_label=question.question,
question_id=question.id,
choices=tuple(likert().items()))
else:
form = SingleStringFieldForm()
if form.validate_on_submit():
if None not in answers.values():
write_answers_to_database(survey=survey)
with open('app/static/ty.txt', 'r') as f:
ty = [x.strip() for x in f.readlines()]
return render_template('ty.html', ty=ty)
return redirect(url_for('survey.question', slug=slug))
return render_template('survey.html', form=form, answers=answers)
The first time I load the page after clearing the session, the form doesn't show up, and when I'm stepping through with a debugger when that happens, the debugger reports that form.answer has a value of:
<UnboundField(RadioField, ('Question 1',), {'choices': (('1', 'Strongly Agree'),
('2', 'Agree'), ('3', 'Neutral'), ('4', 'Disagree'), ('5', 'Strongly Disagree'))})>
If I reload the page, it has this value:
<app.survey.forms.SingleRadioFieldForm object at 0x110788d30>
I don't notice anything else different in the state of the program between the two page loads.
What is causing this the first time and how can I fix it?
While I still don't know why the original function wasn't working on first page load, but did on a reload, I went about this in another way and solved the problem. Instead of setting the fields within __init__, I subclassed within the function and edited the class directly.
#bp.route('/survey/<string:slug>', methods=['GET', 'POST'])
def survey(slug):
class F(FieldsRequiredForm):
pass
...
if None in answers.values():
question = get_next_question()
F.question_id = HiddenField(default=question.id)
if question.category == 'word':
F.answer = StringField(question.question)
elif question.category == 'likert':
F.answer = RadioField(question.question, choices=tuple(likert().items()))
F.submit = SubmitField('Submit')
else:
F.answer = StringField()
form = F()
...

Resources