inpython-package 1.0.8__tar.gz → 1.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {inpython_package-1.0.8/inpython_package.egg-info → inpython_package-1.1.6}/PKG-INFO +15 -2
  2. inpython_package-1.1.6/inpython/inqrcode/__init__.py +6 -0
  3. inpython_package-1.1.6/inpython/inqrcode/inqrcode.py +59 -0
  4. inpython_package-1.1.6/inpython/inqrcode/paymentqrcode.py +129 -0
  5. inpython_package-1.1.6/inpython/inrest/__init__.py +6 -0
  6. inpython_package-1.1.6/inpython/inrest/in_jwt.py +131 -0
  7. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/intools/Servalux-devis.py +58 -58
  8. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/intools/__init__.py +6 -6
  9. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/intools/in_docx.py +61 -61
  10. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/intools/in_projet.py +55 -55
  11. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/intools/in_test.py +3 -3
  12. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/intools/xls_to_csv.py +45 -45
  13. {inpython_package-1.0.8 → inpython_package-1.1.6/inpython_package.egg-info}/PKG-INFO +15 -2
  14. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython_package.egg-info/SOURCES.txt +5 -0
  15. inpython_package-1.1.6/inpython_package.egg-info/requires.txt +5 -0
  16. {inpython_package-1.0.8 → inpython_package-1.1.6}/setup.py +5 -2
  17. inpython_package-1.0.8/inpython_package.egg-info/requires.txt +0 -2
  18. {inpython_package-1.0.8 → inpython_package-1.1.6}/LICENSE.txt +0 -0
  19. {inpython_package-1.0.8 → inpython_package-1.1.6}/README.md +0 -0
  20. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/__init__.py +0 -0
  21. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/__main__.py +0 -0
  22. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/aotools/__init__.py +0 -0
  23. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/aotools/aogeo.py +0 -0
  24. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/ingraph/__init__.py +0 -0
  25. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython/ingraph/ingraph.py +0 -0
  26. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython_package.egg-info/dependency_links.txt +0 -0
  27. {inpython_package-1.0.8 → inpython_package-1.1.6}/inpython_package.egg-info/top_level.txt +0 -0
  28. {inpython_package-1.0.8 → inpython_package-1.1.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: inpython-package
3
- Version: 1.0.8
3
+ Version: 1.1.6
4
4
  Summary: # Infodata's IN-Tools U2Python Package
5
5
  Home-page: https://bitbucket.org/infodata-dev/inpython
6
6
  Author: infodata
@@ -11,6 +11,19 @@ Description-Content-Type: text/markdown
11
11
  License-File: LICENSE.txt
12
12
  Requires-Dist: msal>=1.22
13
13
  Requires-Dist: qrcode
14
+ Requires-Dist: requests
15
+ Requires-Dist: qrcode[pil]
16
+ Requires-Dist: dotenv
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: license
23
+ Dynamic: license-file
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
14
27
 
15
28
  # README
16
29
 
@@ -0,0 +1,6 @@
1
+ # inpython.inqrcode init file
2
+ # executed when 'from inpython.inqrcode import *'
3
+
4
+ # !! update the list when new modules are added !!
5
+
6
+ __all__ = ["inqrcode","paymentqrcode"]
@@ -0,0 +1,59 @@
1
+ """
2
+ script/fonction encode(ErrorCorrection: str = "Q", Valeur: str ) -> str:
3
+ qui execute python qrcode https://pypi.org/project/qrcode/ pour encoder la valeur
4
+ et retourner un tableau de 1010110
5
+
6
+ Usage :
7
+ - Python ...\inqrcode.py codeErr "Valeur"
8
+ Dans ce cas, la fonction sort sur un 'print(result)'
9
+ - from inpython.inqrcode import inqrcode.py
10
+ qrc = inqrcode.encode(codeErr, valeur)
11
+
12
+ """
13
+ import qrcode
14
+ import sys
15
+
16
+ error_correction = {
17
+ 'L': qrcode.ERROR_CORRECT_L,
18
+ 'M': qrcode.ERROR_CORRECT_M,
19
+ 'Q': qrcode.ERROR_CORRECT_Q,
20
+ 'H': qrcode.ERROR_CORRECT_H,
21
+ }
22
+
23
+ def encode(codeErr: str = "M", data: str = "") -> str:
24
+ """fonction qui encode la valeur pour en faire un qrcode avec le module POST
25
+
26
+ Args:
27
+ codeErr (str, optional): Error Correcton level. Defaults to "M".
28
+ The error_correction parameter controls the error correction used for the QR Code. The following four constants are made available on the qrcode package:
29
+ ERROR_CORRECT_L : About 7% or less errors can be corrected.
30
+ ERROR_CORRECT_M (default) : About 15% or less errors can be corrected.
31
+ ERROR_CORRECT_Q : About 25% or less errors can be corrected.
32
+ ERROR_CORRECT_H. : About 30% or less errors can be corrected
33
+ data (str, optional): _description_. Defaults to "".
34
+
35
+ Returns:
36
+ str: sequence de 01010101 emballé sous le format : qrcode<data>\\n-----\\n01010...\\n-----\\n. Separator 'lineFeed' (char(10))
37
+ Exemple :
38
+ qrcode<content_of_arg'data'>
39
+ -----
40
+ 111111101111101111111
41
+ 100000100011101000001
42
+ -----
43
+
44
+ """
45
+ qr = qrcode.QRCode(error_correction=error_correction[codeErr])
46
+ qr.add_data(data)
47
+ qr.border = 0
48
+ qrbool = qr.get_matrix()
49
+ out = sys.stdout
50
+ result = 'qrcode<' + data + '>\n' + '-----\n'
51
+ for l in qrbool:
52
+ s = ''.join(['1' if x else '0' for x in l])
53
+ result += s + '\n'
54
+ result += '-----\n'
55
+ return result
56
+
57
+ if __name__ == "__main__":
58
+ print(encode(sys.argv[1],sys.argv[2]))
59
+
@@ -0,0 +1,129 @@
1
+ import requests
2
+ import qrcode
3
+ from dotenv import load_dotenv
4
+ import os
5
+ from PIL import Image
6
+
7
+ load_dotenv()
8
+
9
+ ADYEN_API_KEY = os.getenv("ADYEN_API_KEY")
10
+ MERCHANT_ACCOUNT = os.getenv("MERCHANT_ACCOUNT")
11
+ URL = os.getenv("ADYEN_API_URL")
12
+
13
+ HEADERS = {
14
+ "X-API-Key": ADYEN_API_KEY,
15
+ "Content-Type": "application/json"
16
+ }
17
+
18
+ def create_payment_link_adyen(amount_cents: int, currency: str, reference: str, mode: str = 1, logo_path: str = None, env_path: str = None, qrcode_path: str = None ) -> str:
19
+ """Crée un lien de paiement via l'API Adyen. Si mode=2, génère aussi un QR code (avec logo si fourni). Si env_path est fourni, charge les variables d'environnement depuis ce fichier."""
20
+ if env_path and os.path.exists(env_path):
21
+ from dotenv import dotenv_values
22
+ env_vars = dotenv_values(env_path)
23
+ adyen_api_key = env_vars.get("ADYEN_API_KEY")
24
+ merchant_account = env_vars.get("MERCHANT_ACCOUNT")
25
+ url = env_vars.get("ADYEN_API_URL")
26
+ else:
27
+ adyen_api_key = ADYEN_API_KEY
28
+ merchant_account = MERCHANT_ACCOUNT
29
+ url = URL
30
+ headers = {
31
+ "X-API-Key": adyen_api_key,
32
+ "Content-Type": "application/json"
33
+ }
34
+ payload = {
35
+ "amount": {
36
+ "value": amount_cents,
37
+ "currency": currency
38
+ },
39
+ "reference": reference,
40
+ "merchantAccount": merchant_account
41
+ }
42
+ response = requests.post(url, headers=headers, json=payload)
43
+ if response.status_code != 200:
44
+ response.raise_for_status()
45
+ data = response.json()
46
+ payment_url = data["url"]
47
+ if mode == 2:
48
+ qr_path = generate_qr_code(payment_url, reference, logo_path,qrcode_path)
49
+ return qr_path
50
+ return payment_url
51
+
52
+ def generate_qr_code(url: str, reference: str, logo_path: str = None, qrcode_path: str = None) -> None:
53
+ """Génère un QR code dans le dossier ./qrcode/ (au même niveau que paymentqrcode.py), avec logo si fourni. Crée/écrase un fichier qrcode_logs.txt pour le diagnostic."""
54
+ import traceback
55
+ base_dir = os.path.dirname(os.path.abspath(__file__))
56
+ output_dir = os.path.join(base_dir, "qrcode")
57
+
58
+ os.makedirs(output_dir, exist_ok=True)
59
+ print("qrcode_path : ",qrcode_path)
60
+ if qrcode_path:
61
+ filename = os.path.join(qrcode_path, f"{reference}.jpg")
62
+ log_file = os.path.join(qrcode_path, "qrcode_debug.log")
63
+ else:
64
+ filename = os.path.join(output_dir, f"{reference}.jpg")
65
+ log_file = os.path.join(output_dir, "qrcode_debug.log")
66
+
67
+ # Supprime le fichier s’il existe
68
+ if os.path.exists(log_file):
69
+ os.remove(log_file)
70
+
71
+ log_lines = []
72
+ try:
73
+ qr = qrcode.QRCode(
74
+ version=1,
75
+ error_correction=qrcode.constants.ERROR_CORRECT_H,
76
+ box_size=10,
77
+ border=4,
78
+ )
79
+ qr.add_data(url)
80
+ qr.make(fit=True)
81
+ img_qr = qr.make_image(fill_color="black", back_color="white").convert('RGB')
82
+ log_lines.append(f"QR code généré pour l'URL: {url}\n")
83
+ if logo_path:
84
+ log_lines.append(f"Chemin du logo fourni: {logo_path}\n")
85
+ if os.path.exists(logo_path):
86
+ try:
87
+ logo = Image.open(logo_path)
88
+ log_lines.append(f"Logo ouvert avec succès. Mode: {logo.mode}, Taille: {logo.size}\n")
89
+ qr_width, qr_height = img_qr.size
90
+ logo_size = int(qr_width * 0.2)
91
+ logo = logo.resize((logo_size, logo_size), Image.LANCZOS)
92
+ log_lines.append(f"Logo redimensionné à: {logo.size}\n")
93
+ pos = ((qr_width - logo_size) // 2, (qr_height - logo_size) // 2)
94
+ img_qr.paste(logo, pos, mask=logo if logo.mode == 'RGBA' else None)
95
+ log_lines.append(f"Logo collé au centre du QR code.\n")
96
+ except Exception as e:
97
+ log_lines.append(f"Erreur lors de l'ouverture ou du collage du logo: {e}\n{traceback.format_exc()}\n")
98
+ else:
99
+ log_lines.append(f"Logo non trouvé : {logo_path}, QR code généré sans logo.\n")
100
+ else:
101
+ log_lines.append("Aucun chemin de logo fourni, QR code généré sans logo.\n")
102
+ img_qr.save(filename, format="JPEG")
103
+ log_lines.append(f"QR code enregistré : {filename}\n")
104
+ except Exception as e:
105
+ log_lines.append(f"Erreur générale lors de la génération du QR code: {e}\n{traceback.format_exc()}\n")
106
+ # Toujours écrire le log, même si une exception a eu lieu
107
+ with open(log_file, 'w') as f:
108
+ f.writelines(log_lines)
109
+ return filename
110
+
111
+
112
+ def clean(s):
113
+ return s.strip('"').strip("'")
114
+
115
+ if __name__ == "__main__":
116
+ import sys
117
+ try:
118
+ # Utilisation : python paymentqrcode.py <mode> <montant> <devise> <reference> [chemin_logo] [chemin_env]
119
+ mode = int(clean(sys.argv[1]))
120
+ amount = int(clean(sys.argv[2]))
121
+ currency = sys.argv[3]
122
+ reference = sys.argv[4]
123
+ logo_path = sys.argv[5] if len(sys.argv) > 5 else ''
124
+ env_path = sys.argv[6] if len(sys.argv) > 6 else ''
125
+ qrcode_path = sys.argv[7] if len(sys.argv) > 7 else ''
126
+ result = create_payment_link_adyen(amount, currency, reference, mode, logo_path, env_path,qrcode_path)
127
+ print(result)
128
+ except Exception as e:
129
+ print("Erreur :", e)
@@ -0,0 +1,6 @@
1
+ # inpython.in_jwt init file
2
+ # executed when 'from inpython.in_jwt import *'
3
+
4
+ # !! update the list when new modules are added !!
5
+
6
+ __all__ = ["in_jwt"]
@@ -0,0 +1,131 @@
1
+ #--------------------------------------------------------
2
+ # Manipulates a Json web token
3
+ #
4
+ #--------------------------------------------------------
5
+ # 22/08/2024 (JCD) : Creation fonction generateJwtClientAssertion
6
+ #--------------------------------------------------------
7
+ from cryptography.hazmat.primitives.serialization import pkcs12
8
+ from cryptography.hazmat.primitives import serialization
9
+ from cryptography.hazmat.backends import default_backend
10
+ import jwt
11
+ import datetime
12
+ import sys
13
+ import getopt
14
+
15
+ # Generates a jwt client assertion from a private key
16
+ def generateJwtClientAssertion(mode,path_certificate,private_key,client_id,audience,expirationTime=10):
17
+ """ Return jwt token assertion
18
+
19
+ Parameters
20
+ ------------
21
+ mode:int
22
+ = 1 : Private key
23
+ = 2 : Private password
24
+ path_certificate: string
25
+ Path crt/cer file if mode = 1
26
+ Path pfx file if mode = 2
27
+ private_key: byte
28
+ Path key file file if mode = 1
29
+ Private password if mode = 2
30
+ client_id: string
31
+ audience: string
32
+ expirationTime: string, Optional
33
+ in minutes. Default to 10 minutes
34
+ """
35
+ try:
36
+ if mode != "1" and mode != "2" :
37
+ raise Exception("Unmanaged mode")
38
+
39
+ if not expirationTime:
40
+ expirationTime = 10
41
+ else:
42
+ expirationTime = int(expirationTime)
43
+
44
+ # Load the public certificate
45
+ with open(path_certificate, "rb") as cert_file:
46
+ certificate_data = cert_file.read()
47
+
48
+ # Load the private key
49
+ if mode == "1":
50
+ with open(private_key, "rb") as key_file:
51
+ private_key = serialization.load_pem_private_key(
52
+ key_file.read(),
53
+ password=None,
54
+ backend=default_backend()
55
+ )
56
+ else:
57
+ private_key, certificate, additional_certs = pkcs12.load_key_and_certificates(
58
+ certificate_data, private_key.encode(), backend=default_backend()
59
+ )
60
+
61
+ now = datetime.datetime.now(datetime.timezone.utc)
62
+ # Define the JWT claims
63
+ claims = {
64
+ "iss": client_id, # The issuer, typically your client ID
65
+ "sub": client_id, # The subject, typically your client ID
66
+ "aud": audience, # The audience, typically the token endpoint URL
67
+ "exp": now + datetime.timedelta(expirationTime), # Expiration time
68
+ "jti": "unique-identifier", # JWT ID, a unique identifier for the JWT
69
+ }
70
+
71
+ # Create the JWT (client assertion)
72
+ if mode == 1:
73
+ client_assertion = jwt.encode(
74
+ claims,
75
+ private_key,
76
+ algorithm="RS256",
77
+ headers={"x5c": [certificate_data.decode("utf-8").replace("\n", "")]}
78
+ )
79
+ else:
80
+ client_assertion = jwt.encode(
81
+ claims, private_key, algorithm="RS256", headers={"alg": "RS256","typ": "JWT"}
82
+ )
83
+ return client_assertion
84
+ except:
85
+ raise # so that the caller receives the exception
86
+
87
+ def main(argv):
88
+ #mode = "1"
89
+ #private_key = "C:\\TRF\\cleanup\\Cleanup1_private.key"
90
+ #path_certificate = "C:\\TRF\\cleanup\\Cleanup1_request.crt"
91
+ #client_id = "self_service_chaman_109660_shr5ppy83v"
92
+
93
+ #mode = "2"
94
+ #path_certificate = "/tmp/jcd/CermiaRest.pfx"
95
+ #private_key = "2024infodd1648!" # Use b'' for an empty password
96
+ #client_id = "self_service_chaman_108306_safnfiag3h"
97
+ #audience = "https://services.socialsecurity.be/REST/oauth/v5/token"
98
+ mode = ''
99
+ private_key = ''
100
+ path_certificate = ''
101
+ client_id = ''
102
+ audience = ''
103
+ expirationTime = None
104
+ try:
105
+ opts, args = getopt.getopt(argv, "m:k:x:c:a:e:", ["mode=", "private_key=", "path_certificate=", "client_id=", "audience=", "expirationTime="])
106
+ except getopt.GetoptError:
107
+ print('script.py -i <inputfile> -o <outputfile>')
108
+ sys.exit(2)
109
+
110
+ for opt, arg in opts:
111
+ if opt in ("-m", "--mode"):
112
+ mode = arg
113
+ elif opt in ("-k", "--private_key"):
114
+ private_key = arg
115
+ elif opt in ("-x", "--path_certificate"):
116
+ path_certificate = arg
117
+ elif opt in ("-c", "--client_id"):
118
+ client_id = arg
119
+ elif opt in ("-a", "--audience"):
120
+ audience = arg
121
+ elif opt in ("-e", "--expirationTime"):
122
+ if arg != "":
123
+ expirationTime = arg
124
+
125
+ result = generateJwtClientAssertion(mode,path_certificate,private_key,client_id,audience,expirationTime)
126
+ print(result)
127
+
128
+ if __name__ == "__main__":
129
+ main(sys.argv[1:])
130
+
131
+
@@ -1,58 +1,58 @@
1
- from docx import Document
2
-
3
- def chk_br(par):
4
- for run in par.r_lst:
5
- if len(run.br_lst) > 0:
6
- return(True)
7
- return(False)
8
-
9
- def build_word_file(doc_directory,fab_filename,skipped_pg_br,keeped_pg_br):
10
- tmp_file = doc_directory + "/schemas.docx"
11
-
12
- print(fab_filename)
13
- doc_fab = Document(fab_filename)
14
- doc_fab.save(tmp_file)
15
- doc_tmp = Document(tmp_file)
16
-
17
- # extraction des pages du docuemnt fabriquant
18
- num_page_breaks = 0
19
-
20
- state = 0
21
-
22
- for elt_idx, elt in enumerate(doc_tmp.element.body):
23
- print(elt.tag)
24
- if state == 0:
25
- if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
26
- if chk_br(elt):
27
- num_page_breaks += 1
28
- if num_page_breaks == 2:
29
- doc_tmp.save(tmp_file)
30
- state = 1
31
- doc_tmp.element.body.remove(elt)
32
- elif state == 1:
33
- if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
34
- if chk_br(elt):
35
- num_page_breaks += 1
36
- if num_page_breaks == 3:
37
- state = 2
38
- doc_tmp.element.body.remove(elt)
39
- #doc_tmp.add_paragraph()
40
- #elif elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tbl":
41
- #table_copy(elt, doc_fab, doc_tmp)
42
- elif state == 2:
43
- if elt.tag != "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}sectPr":
44
- doc_tmp.element.body.remove(elt)
45
-
46
- print("save " + tmp_file)
47
- doc_tmp.save(tmp_file)
48
-
49
- return(tmp_file)
50
-
51
- def build_devis(doc_directory,fab_filename,startdoc,end_doc):
52
- tmp_doc = build_word_file(doc_directory,fab_filename,2,1)
53
- print(tmp_doc)
54
-
55
- doc_dir = "Q:/is/chantier/1000/"
56
- fab_fn = "Q:/is/chantier/1000/FABRIQUANT/1000.docx"
57
-
58
- build_devis(doc_dir,fab_fn,"","")
1
+ from docx import Document
2
+
3
+ def chk_br(par):
4
+ for run in par.r_lst:
5
+ if len(run.br_lst) > 0:
6
+ return(True)
7
+ return(False)
8
+
9
+ def build_word_file(doc_directory,fab_filename,skipped_pg_br,keeped_pg_br):
10
+ tmp_file = doc_directory + "/schemas.docx"
11
+
12
+ print(fab_filename)
13
+ doc_fab = Document(fab_filename)
14
+ doc_fab.save(tmp_file)
15
+ doc_tmp = Document(tmp_file)
16
+
17
+ # extraction des pages du docuemnt fabriquant
18
+ num_page_breaks = 0
19
+
20
+ state = 0
21
+
22
+ for elt_idx, elt in enumerate(doc_tmp.element.body):
23
+ print(elt.tag)
24
+ if state == 0:
25
+ if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
26
+ if chk_br(elt):
27
+ num_page_breaks += 1
28
+ if num_page_breaks == 2:
29
+ doc_tmp.save(tmp_file)
30
+ state = 1
31
+ doc_tmp.element.body.remove(elt)
32
+ elif state == 1:
33
+ if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
34
+ if chk_br(elt):
35
+ num_page_breaks += 1
36
+ if num_page_breaks == 3:
37
+ state = 2
38
+ doc_tmp.element.body.remove(elt)
39
+ #doc_tmp.add_paragraph()
40
+ #elif elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tbl":
41
+ #table_copy(elt, doc_fab, doc_tmp)
42
+ elif state == 2:
43
+ if elt.tag != "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}sectPr":
44
+ doc_tmp.element.body.remove(elt)
45
+
46
+ print("save " + tmp_file)
47
+ doc_tmp.save(tmp_file)
48
+
49
+ return(tmp_file)
50
+
51
+ def build_devis(doc_directory,fab_filename,startdoc,end_doc):
52
+ tmp_doc = build_word_file(doc_directory,fab_filename,2,1)
53
+ print(tmp_doc)
54
+
55
+ doc_dir = "Q:/is/chantier/1000/"
56
+ fab_fn = "Q:/is/chantier/1000/FABRIQUANT/1000.docx"
57
+
58
+ build_devis(doc_dir,fab_fn,"","")
@@ -1,6 +1,6 @@
1
- # inpython.ingraph init file
2
- # executed when 'from inpython.ingraph import *'
3
-
4
- # !! update the list when new modules are added !!
5
-
6
- __all__ = ["xls_to_csv", "in_projet", "in_docx","in_test"]
1
+ # inpython.ingraph init file
2
+ # executed when 'from inpython.ingraph import *'
3
+
4
+ # !! update the list when new modules are added !!
5
+
6
+ __all__ = ["xls_to_csv", "in_projet", "in_docx","in_test"]
@@ -1,61 +1,61 @@
1
- from docx import Document
2
- from docxcompose.composer import Composer
3
-
4
- def chk_br(par):
5
- for run in par.r_lst:
6
- if len(run.br_lst) > 0:
7
- return(True)
8
- return(False)
9
-
10
- def doc_extract(doc_directory,fab_filename,skipped_pg_br,keeped_pg_br):
11
- tmp_file = doc_directory + "/schemas.docx"
12
-
13
- doc_fab = Document(fab_filename)
14
- doc_fab.save(tmp_file)
15
- doc_tmp = Document(tmp_file)
16
-
17
- # extraction des pages du docuemnt fabriquant
18
- num_page_breaks = 0
19
-
20
- state = 0
21
-
22
- for elt_idx, elt in enumerate(doc_tmp.element.body):
23
- if state == 0:
24
- if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
25
- if chk_br(elt):
26
- num_page_breaks += 1
27
- if num_page_breaks == 2:
28
- doc_tmp.save(tmp_file)
29
- state = 1
30
- doc_tmp.element.body.remove(elt)
31
- elif state == 1:
32
- if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
33
- if chk_br(elt):
34
- num_page_breaks += 1
35
- if num_page_breaks == 3:
36
- state = 2
37
- doc_tmp.element.body.remove(elt)
38
- #doc_tmp.add_paragraph()
39
- #elif elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tbl":
40
- #table_copy(elt, doc_fab, doc_tmp)
41
- elif state == 2:
42
- if elt.tag != "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}sectPr":
43
- doc_tmp.element.body.remove(elt)
44
-
45
- doc_tmp.save(tmp_file)
46
-
47
- return(tmp_file)
48
-
49
- def compose_doc(base_file,files_list,final_doc):
50
- files_list = files_list.split(";")
51
- master = Document(base_file)
52
- composer = Composer(master)
53
- for filename in files_list:
54
- doc_temp = Document(filename)
55
- composer.append(doc_temp)
56
- composer.save(final_doc)
57
- return
58
-
59
- if __name__ == '__main__':
60
- flist = ['//winprod/commun/is/chantier/1000/schemas.docx', '//winprod/commun/is/chantier/1000/1000_DETAIL.docx', '//winprod/commun/is/chantier/_doc_base/Formulaire_ALU_cgv.docx']
61
- compose_doc('//winprod/commun/is/chantier/_doc_base/Formulaire_ALU_1-3.docx',flist,'//winprod/commun/is/chantier/1000/Devis.docx')
1
+ from docx import Document
2
+ from docxcompose.composer import Composer
3
+
4
+ def chk_br(par):
5
+ for run in par.r_lst:
6
+ if len(run.br_lst) > 0:
7
+ return(True)
8
+ return(False)
9
+
10
+ def doc_extract(doc_directory,fab_filename,skipped_pg_br,keeped_pg_br):
11
+ tmp_file = doc_directory + "/schemas.docx"
12
+
13
+ doc_fab = Document(fab_filename)
14
+ doc_fab.save(tmp_file)
15
+ doc_tmp = Document(tmp_file)
16
+
17
+ # extraction des pages du docuemnt fabriquant
18
+ num_page_breaks = 0
19
+
20
+ state = 0
21
+
22
+ for elt_idx, elt in enumerate(doc_tmp.element.body):
23
+ if state == 0:
24
+ if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
25
+ if chk_br(elt):
26
+ num_page_breaks += 1
27
+ if num_page_breaks == 2:
28
+ doc_tmp.save(tmp_file)
29
+ state = 1
30
+ doc_tmp.element.body.remove(elt)
31
+ elif state == 1:
32
+ if elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p":
33
+ if chk_br(elt):
34
+ num_page_breaks += 1
35
+ if num_page_breaks == 3:
36
+ state = 2
37
+ doc_tmp.element.body.remove(elt)
38
+ #doc_tmp.add_paragraph()
39
+ #elif elt.tag == "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}tbl":
40
+ #table_copy(elt, doc_fab, doc_tmp)
41
+ elif state == 2:
42
+ if elt.tag != "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}sectPr":
43
+ doc_tmp.element.body.remove(elt)
44
+
45
+ doc_tmp.save(tmp_file)
46
+
47
+ return(tmp_file)
48
+
49
+ def compose_doc(base_file,files_list,final_doc):
50
+ files_list = files_list.split(";")
51
+ master = Document(base_file)
52
+ composer = Composer(master)
53
+ for filename in files_list:
54
+ doc_temp = Document(filename)
55
+ composer.append(doc_temp)
56
+ composer.save(final_doc)
57
+ return
58
+
59
+ if __name__ == '__main__':
60
+ flist = ['//winprod/commun/is/chantier/1000/schemas.docx', '//winprod/commun/is/chantier/1000/1000_DETAIL.docx', '//winprod/commun/is/chantier/_doc_base/Formulaire_ALU_cgv.docx']
61
+ compose_doc('//winprod/commun/is/chantier/_doc_base/Formulaire_ALU_1-3.docx',flist,'//winprod/commun/is/chantier/1000/Devis.docx')
@@ -1,55 +1,55 @@
1
- from docx import Document
2
- from docx.shared import Pt
3
- import csv
4
-
5
- def hello_world():
6
- print('Hello world fron in_projet')
7
-
8
- def build_projet(txt_filename,tpl_filename,doc_filename):
9
- doc_prj = Document(tpl_filename)
10
- font_size = Pt(8)
11
-
12
- ret = False
13
- table = doc_prj.tables[0]
14
-
15
- data = []
16
- # Ouvrir le fichier en mode lecture
17
- with open(txt_filename, 'r', encoding="utf-8") as file:
18
- # Créer un lecteur CSV
19
- reader = csv.reader(file, delimiter=';') # Spécifiez le délimiteur approprié si nécessaire
20
- for rowidx, row in enumerate(reader):
21
- if rowidx >= 11:
22
- if len(row) > 0:
23
- data.append(row)
24
-
25
- current_pos = ''
26
- for posidx, pos in enumerate(data[0]):
27
- if pos != "X":
28
- current_pos = data[1][posidx]
29
- cells = table.add_row().cells
30
- cells[0].text = data[1][posidx]
31
- cells[0].paragraphs[0].runs[0].font.bold = True
32
- text = str(data[4][posidx])
33
- cells[1].text = text.replace("|","\r")
34
- cells[2].text = data[3][posidx]
35
- cells[3].text = data[13][posidx]
36
- cells[4].text = data[5][posidx]
37
- cells[5].text = data[11][posidx]
38
- cells[6].text = data[12][posidx]
39
-
40
- #else:
41
- # print("desigantion = ",data[4][posidx])
42
-
43
- for cell in table._cells:
44
- for paragraph in cell.paragraphs:
45
- for run in paragraph.runs:
46
- run.font.size = font_size
47
- run.font.name = 'Calibri'
48
-
49
- doc_prj.save(doc_filename)
50
- ret = True
51
- return(ret)
52
-
53
- if __name__ == '__main__':
54
- arguments = sys.argv
55
-
1
+ from docx import Document
2
+ from docx.shared import Pt
3
+ import csv
4
+
5
+ def hello_world():
6
+ print('Hello world fron in_projet')
7
+
8
+ def build_projet(txt_filename,tpl_filename,doc_filename):
9
+ doc_prj = Document(tpl_filename)
10
+ font_size = Pt(8)
11
+
12
+ ret = False
13
+ table = doc_prj.tables[0]
14
+
15
+ data = []
16
+ # Ouvrir le fichier en mode lecture
17
+ with open(txt_filename, 'r', encoding="utf-8") as file:
18
+ # Créer un lecteur CSV
19
+ reader = csv.reader(file, delimiter=';') # Spécifiez le délimiteur approprié si nécessaire
20
+ for rowidx, row in enumerate(reader):
21
+ if rowidx >= 11:
22
+ if len(row) > 0:
23
+ data.append(row)
24
+
25
+ current_pos = ''
26
+ for posidx, pos in enumerate(data[0]):
27
+ if pos != "X":
28
+ current_pos = data[1][posidx]
29
+ cells = table.add_row().cells
30
+ cells[0].text = data[1][posidx]
31
+ cells[0].paragraphs[0].runs[0].font.bold = True
32
+ text = str(data[4][posidx])
33
+ cells[1].text = text.replace("|","\r")
34
+ cells[2].text = data[3][posidx]
35
+ cells[3].text = data[13][posidx]
36
+ cells[4].text = data[5][posidx]
37
+ cells[5].text = data[11][posidx]
38
+ cells[6].text = data[12][posidx]
39
+
40
+ #else:
41
+ # print("desigantion = ",data[4][posidx])
42
+
43
+ for cell in table._cells:
44
+ for paragraph in cell.paragraphs:
45
+ for run in paragraph.runs:
46
+ run.font.size = font_size
47
+ run.font.name = 'Calibri'
48
+
49
+ doc_prj.save(doc_filename)
50
+ ret = True
51
+ return(ret)
52
+
53
+ if __name__ == '__main__':
54
+ arguments = sys.argv
55
+
@@ -1,4 +1,4 @@
1
-
2
- def hello_world:
3
- print("salut les aminches")
1
+
2
+ def hello_world:
3
+ print("salut les aminches")
4
4
  return("ça roule ma poule!")
@@ -1,45 +1,45 @@
1
- import pandas as pd
2
- import sys
3
- import csv
4
-
5
- def hello_world():
6
- print('Hello world fron xls_to_csv')
7
-
8
- def parse_csv(csv_file):
9
- # Ouvrir le fichier CSV en mode lecture
10
- with open(csv_file, newline='') as csvfile:
11
- # Créer un lecteur CSV
12
- lecteur_csv = csv.reader(csvfile, delimiter=';')
13
- donnees = list(lecteur_csv)
14
- # Parcourir chaque ligne du fichier CSV
15
- for lindex, ligne in enumerate(donnees):
16
- # Parcourir chaque cellule de la ligne
17
- for cindex, cellule in enumerate(ligne):
18
- if len(cellule) > 0:
19
- donnees[lindex][cindex] = cellule.replace('\n','|')
20
-
21
- with open(csv_file, 'w', newline='') as fichier_sortie:
22
- writer_csv = csv.writer(fichier_sortie, delimiter=';')
23
- # Écrire les données modifiées dans le nouveau fichier CSV
24
- writer_csv.writerows(donnees)
25
-
26
-
27
- def convert_to_csv(xls_file,csv_file):
28
- df = pd.read_excel(xls_file)
29
- df.to_csv(csv_file, index=False, sep=';')
30
- parse_csv(csv_file)
31
- return
32
-
33
- if __name__ == '__main__':
34
- arguments = sys.argv
35
-
36
- if len(arguments) == 3:
37
- xl_filename = arguments[1].replace('\\','/') # Premier argument
38
- csv_filename = arguments[2].replace('\\','/') # Deuxième argument
39
- convert_to_csv(xl_filename, csv_filename)
40
- else:
41
- xl_filename = "Q:/is/chantier/1000/1000_DETAIL.xlsx" # Premier argument
42
- csv_filename = "Q:/is/chantier/1000/1000_DETAIL.csv" # Deuxième argument
43
- convert_to_csv(xl_filename, csv_filename)
44
- print("Veuillez spécifier des arguments.")
45
-
1
+ import pandas as pd
2
+ import sys
3
+ import csv
4
+
5
+ def hello_world():
6
+ print('Hello world fron xls_to_csv')
7
+
8
+ def parse_csv(csv_file):
9
+ # Ouvrir le fichier CSV en mode lecture
10
+ with open(csv_file, newline='') as csvfile:
11
+ # Créer un lecteur CSV
12
+ lecteur_csv = csv.reader(csvfile, delimiter=';')
13
+ donnees = list(lecteur_csv)
14
+ # Parcourir chaque ligne du fichier CSV
15
+ for lindex, ligne in enumerate(donnees):
16
+ # Parcourir chaque cellule de la ligne
17
+ for cindex, cellule in enumerate(ligne):
18
+ if len(cellule) > 0:
19
+ donnees[lindex][cindex] = cellule.replace('\n','|')
20
+
21
+ with open(csv_file, 'w', newline='') as fichier_sortie:
22
+ writer_csv = csv.writer(fichier_sortie, delimiter=';')
23
+ # Écrire les données modifiées dans le nouveau fichier CSV
24
+ writer_csv.writerows(donnees)
25
+
26
+
27
+ def convert_to_csv(xls_file,csv_file):
28
+ df = pd.read_excel(xls_file)
29
+ df.to_csv(csv_file, index=False, sep=';')
30
+ parse_csv(csv_file)
31
+ return
32
+
33
+ if __name__ == '__main__':
34
+ arguments = sys.argv
35
+
36
+ if len(arguments) == 3:
37
+ xl_filename = arguments[1].replace('\\','/') # Premier argument
38
+ csv_filename = arguments[2].replace('\\','/') # Deuxième argument
39
+ convert_to_csv(xl_filename, csv_filename)
40
+ else:
41
+ xl_filename = "Q:/is/chantier/1000/1000_DETAIL.xlsx" # Premier argument
42
+ csv_filename = "Q:/is/chantier/1000/1000_DETAIL.csv" # Deuxième argument
43
+ convert_to_csv(xl_filename, csv_filename)
44
+ print("Veuillez spécifier des arguments.")
45
+
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: inpython-package
3
- Version: 1.0.8
3
+ Version: 1.1.6
4
4
  Summary: # Infodata's IN-Tools U2Python Package
5
5
  Home-page: https://bitbucket.org/infodata-dev/inpython
6
6
  Author: infodata
@@ -11,6 +11,19 @@ Description-Content-Type: text/markdown
11
11
  License-File: LICENSE.txt
12
12
  Requires-Dist: msal>=1.22
13
13
  Requires-Dist: qrcode
14
+ Requires-Dist: requests
15
+ Requires-Dist: qrcode[pil]
16
+ Requires-Dist: dotenv
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: license
23
+ Dynamic: license-file
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
14
27
 
15
28
  # README
16
29
 
@@ -7,6 +7,11 @@ inpython/aotools/__init__.py
7
7
  inpython/aotools/aogeo.py
8
8
  inpython/ingraph/__init__.py
9
9
  inpython/ingraph/ingraph.py
10
+ inpython/inqrcode/__init__.py
11
+ inpython/inqrcode/inqrcode.py
12
+ inpython/inqrcode/paymentqrcode.py
13
+ inpython/inrest/__init__.py
14
+ inpython/inrest/in_jwt.py
10
15
  inpython/intools/Servalux-devis.py
11
16
  inpython/intools/__init__.py
12
17
  inpython/intools/in_docx.py
@@ -0,0 +1,5 @@
1
+ msal>=1.22
2
+ qrcode
3
+ requests
4
+ qrcode[pil]
5
+ dotenv
@@ -9,7 +9,7 @@ with open("README.md", "r") as fh:
9
9
 
10
10
  setup(
11
11
  name="inpython-package",
12
- version="1.0.8",
12
+ version="1.1.6",
13
13
  author="infodata",
14
14
  author_email="efv@infodata.lu",
15
15
  packages=find_packages(),
@@ -21,6 +21,9 @@ setup(
21
21
  python_requires='>=3.4',
22
22
  install_requires=[
23
23
  'msal >= 1.22',
24
- 'qrcode'
24
+ 'qrcode',
25
+ 'requests',
26
+ 'qrcode[pil]',
27
+ 'dotenv'
25
28
  ]
26
29
  )
@@ -1,2 +0,0 @@
1
- msal>=1.22
2
- qrcode