LuisBlanche commited on
Commit
44f9c40
1 Parent(s): 7065c44

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +288 -98
app.py CHANGED
@@ -1,41 +1,279 @@
1
  import gradio as gr
2
  import numpy as np
3
  import random
4
- from diffusers import DiffusionPipeline
5
- import torch
6
 
7
- device = "cuda" if torch.cuda.is_available() else "cpu"
8
 
9
- if torch.cuda.is_available():
10
- torch.cuda.max_memory_allocated(device=device)
11
- pipe = DiffusionPipeline.from_pretrained("stabilityai/sdxl-turbo", torch_dtype=torch.float16, variant="fp16", use_safetensors=True)
12
- pipe.enable_xformers_memory_efficient_attention()
13
- pipe = pipe.to(device)
14
- else:
15
- pipe = DiffusionPipeline.from_pretrained("stabilityai/sdxl-turbo", use_safetensors=True)
16
- pipe = pipe.to(device)
17
 
18
- MAX_SEED = np.iinfo(np.int32).max
19
- MAX_IMAGE_SIZE = 1024
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- def infer(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps):
22
 
23
- if randomize_seed:
24
- seed = random.randint(0, MAX_SEED)
25
-
26
- generator = torch.Generator().manual_seed(seed)
27
-
28
- image = pipe(
29
- prompt = prompt,
30
- negative_prompt = negative_prompt,
31
- guidance_scale = guidance_scale,
32
- num_inference_steps = num_inference_steps,
33
- width = width,
34
- height = height,
35
- generator = generator
36
- ).images[0]
37
-
38
- return image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  examples = [
41
  "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k",
@@ -50,96 +288,48 @@ css="""
50
  }
51
  """
52
 
53
- if torch.cuda.is_available():
54
- power_device = "GPU"
55
- else:
56
- power_device = "CPU"
57
 
58
  with gr.Blocks(css=css) as demo:
59
 
60
  with gr.Column(elem_id="col-container"):
61
  gr.Markdown(f"""
62
- # Text-to-Image Gradio Template
63
- Currently running on {power_device}.
64
  """)
65
 
66
  with gr.Row():
67
 
68
- prompt = gr.Text(
69
- label="Prompt",
70
  show_label=False,
71
  max_lines=1,
72
- placeholder="Enter your prompt",
73
  container=False,
74
  )
75
 
76
  run_button = gr.Button("Run", scale=0)
77
 
78
- result = gr.Image(label="Result", show_label=False)
79
 
80
- with gr.Accordion("Advanced Settings", open=False):
81
-
82
- negative_prompt = gr.Text(
83
- label="Negative prompt",
84
- max_lines=1,
85
- placeholder="Enter a negative prompt",
86
- visible=False,
87
- )
88
-
89
- seed = gr.Slider(
90
- label="Seed",
91
- minimum=0,
92
- maximum=MAX_SEED,
93
- step=1,
94
- value=0,
95
- )
96
 
97
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
98
-
99
- with gr.Row():
100
-
101
- width = gr.Slider(
102
- label="Width",
103
- minimum=256,
104
- maximum=MAX_IMAGE_SIZE,
105
- step=32,
106
- value=512,
107
- )
108
-
109
- height = gr.Slider(
110
- label="Height",
111
- minimum=256,
112
- maximum=MAX_IMAGE_SIZE,
113
- step=32,
114
- value=512,
115
- )
116
-
117
- with gr.Row():
118
-
119
- guidance_scale = gr.Slider(
120
- label="Guidance scale",
121
- minimum=0.0,
122
- maximum=10.0,
123
- step=0.1,
124
- value=0.0,
125
- )
126
-
127
- num_inference_steps = gr.Slider(
128
- label="Number of inference steps",
129
- minimum=1,
130
- maximum=12,
131
- step=1,
132
- value=2,
133
- )
134
-
135
- gr.Examples(
136
- examples = examples,
137
- inputs = [prompt]
138
  )
 
 
 
 
 
 
 
 
139
 
140
  run_button.click(
141
  fn = infer,
142
- inputs = [prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps],
143
  outputs = [result]
144
  )
145
 
 
1
  import gradio as gr
2
  import numpy as np
3
  import random
 
 
4
 
 
5
 
6
+ import re
7
+ from io import BytesIO
 
 
 
 
 
 
8
 
9
+ import mechanicalsoup
10
+ import pandas as pd
11
+ import requests
12
+ from reportlab.lib import colors
13
+ from reportlab.lib.enums import TA_CENTER
14
+ from reportlab.lib.pagesizes import A4
15
+ from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
16
+ from reportlab.lib.units import cm
17
+ from reportlab.platypus import (
18
+ Image,
19
+ Paragraph,
20
+ SimpleDocTemplate,
21
+ Spacer,
22
+ Table,
23
+ TableStyle,
24
+ )
25
+ from unidecode import unidecode
26
 
 
27
 
28
+ class PDFPoster:
29
+ def __init__(self, deputy_name: str, vote_id_list: list[str]):
30
+ self.deputy_name = deputy_name
31
+ self.vote_id_list = [f"vote_{i}" for i in vote_id_list]
32
+
33
+ def retrieve_deputy_data(self):
34
+ self.deputy_data = self.get_deputy_votes_page()
35
+ self.votes = self.get_votes_from_politic_page()
36
+ self.img_url = self.get_politic_image()
37
+ self.party = self.get_politic_party()
38
+
39
+ def generate_poster(
40
+ self,
41
+ message_1: str = "Les votes de vos députés sont souvent différents de ce que les responsables de partis annoncent dans les médias. Les données de votes sont ouvertes!",
42
+ message_2: str = "Les 30 juin, et 7 juin, renseignez vous, et votez en connaissance de cause !",
43
+ ):
44
+ self.retrieve_deputy_data()
45
+ df_subset = self.votes[self.votes["vote_id"].isin(self.vote_id_list)]
46
+
47
+ pdf_filename = f"{self.deputy_name}.pdf"
48
+ document = SimpleDocTemplate(pdf_filename, pagesize=A4)
49
+
50
+ # Set up the styles
51
+ styles = getSampleStyleSheet()
52
+ title_style = styles["Title"]
53
+ title_style.alignment = TA_CENTER
54
+ subtitle_style = styles["Heading2"]
55
+ subtitle_style.alignment = TA_CENTER
56
+ subtitle_style.fontName = "Helvetica-Bold"
57
+
58
+ normal_style = styles["Normal"]
59
+ normal_style.alignment = TA_CENTER
60
+
61
+ red_style = ParagraphStyle(
62
+ "red", parent=subtitle_style, textColor=colors.red, fontSize=20
63
+ )
64
+
65
+ # Add a title
66
+ title = Paragraph(
67
+ f"Les votes de votre député sortant : {self.deputy_name}", title_style
68
+ )
69
+ subtitle = Paragraph(f"Parti : {self.party} ", subtitle_style)
70
+ source = Paragraph(f"Source : {self.deputy_data['url']}", normal_style)
71
+ after_text = Paragraph(message_1, subtitle_style)
72
+ vote_text = Paragraph(message_2, red_style)
73
+
74
+ # Add an image
75
+ # Open the image URL with BytesIO
76
+ image_response = requests.get(self.img_url)
77
+ image_bytes = BytesIO(image_response.content)
78
+ image = Image(image_bytes)
79
+ image.drawHeight = 6 * cm
80
+ image.drawWidth = 5 * cm
81
+
82
+ # Create a list of sentences
83
+ sentences = df_subset["vote_topic"].tolist()
84
+ votes = df_subset["for_or_against"].tolist()
85
+
86
+ # Create the table data
87
+ table_data = [["Sujet", "Vote"]]
88
+ for vote, sentence in zip(sentences, votes):
89
+ row = [
90
+ Paragraph(vote, normal_style),
91
+ Paragraph(sentence, normal_style),
92
+ ]
93
+ table_data.append(row)
94
+
95
+ # Create the table
96
+ table = Table(table_data)
97
+ table.setStyle(
98
+ TableStyle(
99
+ [
100
+ ("BACKGROUND", (0, 0), (-1, 0), colors.white),
101
+ ("TEXTCOLOR", (0, 0), (-1, 0), colors.black),
102
+ ("ALIGN", (0, 0), (-1, -1), "CENTER"),
103
+ ("FONTNAME", (0, 0), (-1, 1), "Helvetica-Bold"),
104
+ ("FONTSIZE", (0, 0), (-1, 0), 14),
105
+ ("BOTTOMPADDING", (0, 0), (-1, 0), 12),
106
+ ("ALIGN", (0, 1), (-1, -1), "CENTER"),
107
+ ("BACKGROUND", (0, 1), (-1, -1), colors.white),
108
+ ("GRID", (0, 0), (-1, -1), 1, colors.black),
109
+ ]
110
+ )
111
+ )
112
+
113
+ # Function to apply conditional formatting
114
+ def apply_conditional_styles(table, data):
115
+ style = TableStyle()
116
+ for row_idx, row in enumerate(data):
117
+ for col_idx, cell in enumerate(row):
118
+ if isinstance(cell, Paragraph):
119
+ if "POUR" in cell.text:
120
+ style.add(
121
+ "BACKGROUND",
122
+ (col_idx, row_idx),
123
+ (col_idx, row_idx),
124
+ colors.green,
125
+ )
126
+ elif "CONTRE" in cell.text:
127
+ style.add(
128
+ "BACKGROUND",
129
+ (col_idx, row_idx),
130
+ (col_idx, row_idx),
131
+ colors.red,
132
+ )
133
+ elif "ABSTENTION" in cell.text:
134
+ style.add(
135
+ "BACKGROUND",
136
+ (col_idx, row_idx),
137
+ (col_idx, row_idx),
138
+ colors.beige,
139
+ )
140
+ return style
141
+
142
+ table.setStyle(apply_conditional_styles(table, table_data))
143
+
144
+ # Build the PDF
145
+ elements = [
146
+ title,
147
+ Spacer(1, 6),
148
+ subtitle,
149
+ Spacer(1, 12),
150
+ image,
151
+ Spacer(1, 12),
152
+ table,
153
+ source,
154
+ Spacer(1, 8),
155
+ after_text,
156
+ Spacer(1, 8),
157
+ vote_text,
158
+ ]
159
+ document.build(elements)
160
+
161
+ def get_deputy_votes_page(self):
162
+ """Fetches the webpage containing the voting records of a specified deputy.
163
+
164
+ Args:
165
+ politic_name (str): Name of the deputy.
166
+ Returns:
167
+ politic_dict (dict): Dictionary containing the html page, the url and the
168
+ name of the deputy."""
169
+ politic_name = unidecode(self.deputy_name.lower()).replace(" ", "-")
170
+
171
+ browser = mechanicalsoup.StatefulBrowser()
172
+ url = "https://datan.fr/deputes"
173
+ research_page = browser.open(url)
174
+ research_html = research_page.soup
175
+
176
+ politic_card = research_html.select(f'a[href*="{politic_name}"]')
177
+ if politic_card:
178
+ url_politic = politic_card[0]["href"]
179
+ politic_page = browser.open(url_politic + "/votes")
180
+ politic_html = politic_page.soup
181
+ politic_dict = {
182
+ "html_page": politic_html,
183
+ "url": url_politic,
184
+ "name": politic_name,
185
+ }
186
+ return politic_dict
187
+ else:
188
+ raise ValueError(f"Politic {politic_name} not found")
189
+
190
+ def get_votes_from_politic_page(self):
191
+ """Extracts the voting records from the html page of a deputy.
192
+
193
+ Args:
194
+ politic_dict (dict): Dictionary containing the html page, the url and the
195
+ name of the deputy.
196
+ Returns:
197
+ df (pd.DataFrame): DataFrame containing the voting records of the deputy."""
198
+ # <div class="col-md-6 sorting-item institutions" style="position: absolute; left: 0px; top: 0px;">
199
+ politic_html = self.deputy_data["html_page"]
200
+ politic_name = self.deputy_data["name"]
201
+ vote_elements = politic_html.find_all("div", class_="card card-vote")
202
+ vote_categories = politic_html.find_all(
203
+ class_=re.compile("col-md-6 sorting-item*")
204
+ )
205
+ votes = []
206
+ for i, vote_element in enumerate(vote_elements):
207
+ for_or_against = (
208
+ vote_element.find("div", class_="d-flex align-items-center")
209
+ .text.replace("\n", "")
210
+ .strip()
211
+ )
212
+ vote_topic = (
213
+ vote_element.find("a", class_="stretched-link underline no-decoration")
214
+ .text.replace("\n", "")
215
+ .strip()
216
+ )
217
+ vote_id = (
218
+ vote_element.find("a", class_="stretched-link underline no-decoration")[
219
+ "href"
220
+ ]
221
+ .split("/")[-1]
222
+ .replace("\n", "")
223
+ .strip()
224
+ )
225
+ vote_date = (
226
+ vote_element.find("span", class_="date").text.replace("\n", "").strip()
227
+ )
228
+ vote_category = vote_categories[i]["class"][-1]
229
+ # color = "green" if for_or_against == "Pour" else "red"
230
+ votes.append(
231
+ [
232
+ vote_id,
233
+ for_or_against,
234
+ vote_topic,
235
+ vote_date,
236
+ politic_name,
237
+ vote_category,
238
+ ]
239
+ )
240
+ df = pd.DataFrame(
241
+ votes,
242
+ columns=[
243
+ "vote_id",
244
+ "for_or_against",
245
+ "vote_topic",
246
+ "vote_date",
247
+ "politic_name",
248
+ "vote_category",
249
+ ],
250
+ )
251
+ return df
252
+
253
+ def get_politic_image(self):
254
+ """Fetches the image of a deputy.
255
+
256
+ Args:
257
+ politic_name (str): Name of the deputy.
258
+ Returns:
259
+ image (str): URL of the image of the deputy."""
260
+ image = self.deputy_data["html_page"].find("img", alt=self.deputy_name)
261
+ image_src = image.get("src")
262
+ return image_src
263
+
264
+ def get_politic_party(self):
265
+ party = (
266
+ self.deputy_data["html_page"]
267
+ .find("div", class_="link-group text-center mt-1")
268
+ .text.replace("\n", "")
269
+ .strip()
270
+ )
271
+ return party
272
+
273
+
274
+ def infer(deputy_name, message_1, message_2):
275
+ pdfposter = PDFPoster(deputy_name)
276
+
277
 
278
  examples = [
279
  "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k",
 
288
  }
289
  """
290
 
291
+
 
 
 
292
 
293
  with gr.Blocks(css=css) as demo:
294
 
295
  with gr.Column(elem_id="col-container"):
296
  gr.Markdown(f"""
297
+ # Réalise une affiche des votes de ton député !
 
298
  """)
299
 
300
  with gr.Row():
301
 
302
+ deputy = gr.Text(
303
+ label="deputy_name",
304
  show_label=False,
305
  max_lines=1,
306
+ placeholder="Nom du député, si tu ne le connais pas RDV sur www.datan.fr ou www.nosdeputes.fr",
307
  container=False,
308
  )
309
 
310
  run_button = gr.Button("Run", scale=0)
311
 
312
+ result = gr.File(label="Result", show_label=True)
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
+ message_1 = gr.Text(
316
+ label="message_1",
317
+ max_lines=1,
318
+ placeholder="Les votes de vos députés sont souvent différents de ce que les responsables de partis annoncent dans les médias. Les données de votes sont ouvertes!",
319
+ visible=False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  )
321
+ message_2 = gr.Text(
322
+ label="message_2",
323
+ max_lines=1,
324
+ placeholder="Les 30 juin, et 7 juin, renseignez vous, et votez en connaissance de cause !",
325
+ visible=False,
326
+ )
327
+
328
+
329
 
330
  run_button.click(
331
  fn = infer,
332
+ inputs = [deputy, message_1, message_2],
333
  outputs = [result]
334
  )
335