slthcore 0.1.3__tar.gz → 0.1.5__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.

Potentially problematic release.


This version of slthcore might be problematic. Click here for more details.

Files changed (83) hide show
  1. {slthcore-0.1.3/slthcore.egg-info → slthcore-0.1.5}/PKG-INFO +1 -1
  2. {slthcore-0.1.3 → slthcore-0.1.5}/setup.py +1 -1
  3. {slthcore-0.1.3 → slthcore-0.1.5}/slth/__init__.py +13 -2
  4. {slthcore-0.1.3 → slthcore-0.1.5}/slth/endpoints.py +0 -3
  5. slthcore-0.1.5/slth/pdf/__init__.py +177 -0
  6. slthcore-0.1.5/slth/pdf/tests.py +70 -0
  7. {slthcore-0.1.3 → slthcore-0.1.5}/slth/selenium/__init__.py +1 -0
  8. {slthcore-0.1.3 → slthcore-0.1.5/slthcore.egg-info}/PKG-INFO +1 -1
  9. {slthcore-0.1.3 → slthcore-0.1.5}/slthcore.egg-info/SOURCES.txt +2 -0
  10. {slthcore-0.1.3 → slthcore-0.1.5}/MANIFEST.in +0 -0
  11. {slthcore-0.1.3 → slthcore-0.1.5}/setup.cfg +0 -0
  12. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/configure/__main__.py +0 -0
  13. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/__main__.py +0 -0
  14. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/.DS_Store +0 -0
  15. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/.gitignore +0 -0
  16. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/__init__.py +0 -0
  17. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/asgi.py +0 -0
  18. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/endpoints.py +0 -0
  19. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/models.py +0 -0
  20. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/settings.py +0 -0
  21. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/tests.py +0 -0
  22. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/urls.py +0 -0
  23. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/api/wsgi.py +0 -0
  24. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/application.yml +0 -0
  25. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/entrypoint.sh +0 -0
  26. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/manage.py +0 -0
  27. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/backend/requirements.txt +0 -0
  28. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/base.env +0 -0
  29. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/docker-compose.yml +0 -0
  30. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/frontend/package.json +0 -0
  31. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/frontend/src/main.jsx +0 -0
  32. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/frontend/vite.config.js +0 -0
  33. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/local.env +0 -0
  34. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/run.sh +0 -0
  35. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/selenium/run.sh +0 -0
  36. {slthcore-0.1.3 → slthcore-0.1.5}/slth/cmd/init/boilerplate/test.sh +0 -0
  37. {slthcore-0.1.3 → slthcore-0.1.5}/slth/components.py +0 -0
  38. {slthcore-0.1.3 → slthcore-0.1.5}/slth/db/__init__.py +0 -0
  39. {slthcore-0.1.3 → slthcore-0.1.5}/slth/db/generic.py +0 -0
  40. {slthcore-0.1.3 → slthcore-0.1.5}/slth/db/models.py +0 -0
  41. {slthcore-0.1.3 → slthcore-0.1.5}/slth/exceptions.py +0 -0
  42. {slthcore-0.1.3 → slthcore-0.1.5}/slth/factory.py +0 -0
  43. {slthcore-0.1.3 → slthcore-0.1.5}/slth/forms.py +0 -0
  44. {slthcore-0.1.3 → slthcore-0.1.5}/slth/management/__init__.py +0 -0
  45. {slthcore-0.1.3 → slthcore-0.1.5}/slth/management/commands/__init__.py +0 -0
  46. {slthcore-0.1.3 → slthcore-0.1.5}/slth/management/commands/integration_test.py +0 -0
  47. {slthcore-0.1.3 → slthcore-0.1.5}/slth/management/commands/sync.py +0 -0
  48. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0001_initial.py +0 -0
  49. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0002_email_role_pushsubscription_error.py +0 -0
  50. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0003_rename_photo_profile_alter_profile_options.py +0 -0
  51. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0004_alter_profile_photo.py +0 -0
  52. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0005_alter_profile_photo.py +0 -0
  53. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0006_user.py +0 -0
  54. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/0007_deletion_log.py +0 -0
  55. {slthcore-0.1.3 → slthcore-0.1.5}/slth/migrations/__init__.py +0 -0
  56. {slthcore-0.1.3 → slthcore-0.1.5}/slth/models.py +0 -0
  57. {slthcore-0.1.3 → slthcore-0.1.5}/slth/notifications.py +0 -0
  58. {slthcore-0.1.3 → slthcore-0.1.5}/slth/oauth.py +0 -0
  59. {slthcore-0.1.3 → slthcore-0.1.5}/slth/permissions.py +0 -0
  60. {slthcore-0.1.3 → slthcore-0.1.5}/slth/printer.py +0 -0
  61. {slthcore-0.1.3 → slthcore-0.1.5}/slth/queryset.py +0 -0
  62. {slthcore-0.1.3 → slthcore-0.1.5}/slth/roles.py +0 -0
  63. {slthcore-0.1.3 → slthcore-0.1.5}/slth/selenium/browser.py +0 -0
  64. {slthcore-0.1.3 → slthcore-0.1.5}/slth/serializer.py +0 -0
  65. {slthcore-0.1.3 → slthcore-0.1.5}/slth/static/.DS_Store +0 -0
  66. {slthcore-0.1.3 → slthcore-0.1.5}/slth/static/css/.DS_Store +0 -0
  67. {slthcore-0.1.3 → slthcore-0.1.5}/slth/static/css/slth.css +0 -0
  68. {slthcore-0.1.3 → slthcore-0.1.5}/slth/static/js/index.min.js +0 -0
  69. {slthcore-0.1.3 → slthcore-0.1.5}/slth/static/js/react.min.js +0 -0
  70. {slthcore-0.1.3 → slthcore-0.1.5}/slth/static/js/slth.min.js +0 -0
  71. {slthcore-0.1.3 → slthcore-0.1.5}/slth/statistics.py +0 -0
  72. {slthcore-0.1.3 → slthcore-0.1.5}/slth/tasks.py +0 -0
  73. {slthcore-0.1.3 → slthcore-0.1.5}/slth/templates/index.html +0 -0
  74. {slthcore-0.1.3 → slthcore-0.1.5}/slth/templates/report.html +0 -0
  75. {slthcore-0.1.3 → slthcore-0.1.5}/slth/templates/service-worker.js +0 -0
  76. {slthcore-0.1.3 → slthcore-0.1.5}/slth/templates/signature.html +0 -0
  77. {slthcore-0.1.3 → slthcore-0.1.5}/slth/tests.py +0 -0
  78. {slthcore-0.1.3 → slthcore-0.1.5}/slth/threadlocal.py +0 -0
  79. {slthcore-0.1.3 → slthcore-0.1.5}/slth/urls.py +0 -0
  80. {slthcore-0.1.3 → slthcore-0.1.5}/slth/utils.py +0 -0
  81. {slthcore-0.1.3 → slthcore-0.1.5}/slth/views.py +0 -0
  82. {slthcore-0.1.3 → slthcore-0.1.5}/slthcore.egg-info/dependency_links.txt +0 -0
  83. {slthcore-0.1.3 → slthcore-0.1.5}/slthcore.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: slthcore
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: API generator based on yml file
5
5
  Home-page: https://github.com/brenokcc
6
6
  Author: Breno Silva
@@ -5,7 +5,7 @@ install_requires = []
5
5
 
6
6
  setup(
7
7
  name='slthcore',
8
- version='0.1.3',
8
+ version='0.1.5',
9
9
  packages=find_packages(),
10
10
  install_requires=install_requires,
11
11
  include_package_data=True,
@@ -4,7 +4,7 @@ import yaml
4
4
  import json
5
5
  import warnings
6
6
  from pathlib import Path
7
- from datetime import datetime
7
+ from datetime import datetime, date
8
8
  from django.apps import apps
9
9
  from django.db import models
10
10
  from .queryset import QuerySet
@@ -19,6 +19,8 @@ from django.utils.autoreload import autoreload_started
19
19
  from django.core import serializers
20
20
  from .threadlocal import tl
21
21
 
22
+ from decimal import Decimal
23
+
22
24
  warnings.filterwarnings('ignore', module='urllib3')
23
25
 
24
26
  FILENAME = 'application.yml'
@@ -34,6 +36,15 @@ if APPLICATON is None and os.path.exists(FILENAME):
34
36
  APPLICATON = yaml.safe_load(content).get('application')
35
37
 
36
38
 
39
+ class JSONEncoder(json.JSONEncoder):
40
+ def default(self, obj):
41
+ if isinstance(obj, Decimal):
42
+ return float(obj)
43
+ if isinstance(obj, date):
44
+ return obj.strftime("%d-%m-%Y")
45
+ return json.JSONEncoder.default(self, obj)
46
+
47
+
37
48
  class BaseManager(manager.BaseManager):
38
49
  def get_queryset(self):
39
50
  return super().get_queryset()
@@ -120,7 +131,7 @@ class ModelMixin(object):
120
131
  objects.append(instance)
121
132
  if instance.__class__.__name__ not in order:
122
133
  order.append(instance.__class__.__name__)
123
- backup = json.dumps(dict(order=order, objects=serializers.serialize("python", objects)))
134
+ backup = json.dumps(dict(order=order, objects=serializers.serialize("python", objects)), cls=JSONEncoder)
124
135
  instance = '{}.{}:{}'.format(self._meta.app_label, self._meta.model_name, self.pk)
125
136
  Deletion.objects.create(username=username, datetime=datetime.now(), instance=instance, backup=backup)
126
137
  return self.delete()
@@ -330,7 +330,6 @@ class Endpoint(metaclass=EnpointMetaclass):
330
330
  if hasattr(tl, 'context') and tl.context['logs']:
331
331
  pk = tl.context['pk']
332
332
  instance = self.get_instance()
333
- print(tl.context)
334
333
  if pk or isinstance(instance, Model):
335
334
  model = '{}.{}'.format(instance._meta.app_label, instance._meta.model_name)
336
335
  tl.context.update(model=model, pk=pk or instance.pk)
@@ -823,8 +822,6 @@ class Application(PublicEndpoint):
823
822
  icon, label = k.split(":") if ":" in k else (None, k)
824
823
  url = build_url(self.request, cls.get_api_url())
825
824
  return dict(dict(label=label, url=url, icon=icon))
826
- else:
827
- print(v)
828
825
 
829
826
  for k, v in APPLICATON["menu"].items():
830
827
  item = get_item(k, v)
@@ -0,0 +1,177 @@
1
+ # pip install --upgrade fpdf2
2
+ from fpdf import FPDF, FontFace
3
+ import hashlib
4
+ import base64
5
+ import os
6
+ import re
7
+ import requests
8
+ from datetime import datetime
9
+ import tempfile
10
+ from PIL import Image, ImageDraw, ImageFont
11
+ from django.template.loader import render_to_string
12
+ from django.conf import settings
13
+
14
+ SIGNATURE_URL = 'https://assinatura-api.staging.iti.br/externo/v2/assinarPKCS7'
15
+ SIGNATURE_SIZE = 18944
16
+ BYTERANGE='[ ]'
17
+
18
+ STYLE = {
19
+ 'h1': FontFace(color="#000000", size_pt=28, family='Helvetica'),
20
+ 'h2': FontFace(color="#000000", size_pt=24, family='Helvetica'),
21
+ }
22
+
23
+ class PdfWriter:
24
+ def __init__(self):
25
+ self.pdf = FPDF()
26
+ self.pdf.add_page()
27
+
28
+ def render(self, template_name, context):
29
+ context.update(base_url=settings.SITE_URL)
30
+ html = render_to_string(template_name, context)
31
+ self.pdf.write_html(html, tag_styles=STYLE, font_family="Courier")
32
+
33
+ def save(self, path):
34
+ self.pdf.output(path)
35
+
36
+
37
+ class PdfSigner:
38
+ def __init__(self, path, signer):
39
+ self.path = path
40
+ self.signer = signer
41
+ self.xref = None
42
+ self.data = []
43
+ with open(path, 'rb') as fp:
44
+ self.content = fp.read()# + b'\r\n'
45
+ self.offset = len(self.content)
46
+ self.byterange = []
47
+ self.path = path.split('.')[0]
48
+ self.startxref = [int(x[9:].strip()) for x in re.findall(b'startxref[\n\r ]*\d+', self.content)]
49
+ self.objects = {}
50
+ for xref in re.findall(b'xref[\n\r\w\d ]*trailer', self.content[self.startxref[0]:]):
51
+ for offset in sum([[int(n) for n in re.findall(b'\d{10}', xref) if int(n)]], []):
52
+ self.objects[b' '.join(self.content[offset:offset + 15].split()[0:2]).decode()] = offset
53
+ self.trailer = self.content[self.startxref[-1]:].split(b'trailer')[1].split(b'startxref')[0].strip()
54
+ self.root = root = re.findall(b'/Root \d+ \d+ R', self.trailer)[-1][6:-2].decode()
55
+ self.size = int(re.findall(b'/Size \d+', self.trailer)[-1][5:].strip())
56
+ self.page()
57
+
58
+ def obj(self, key=None):
59
+ key = key or self.root
60
+ return self.content[self.objects[key]: self.objects[key] + self.content[self.objects[key]:].index(b'endobj') + 6].replace(b'\r', b'') + b'\n'
61
+
62
+ def next(self, i):
63
+ return max([int(k.split()[0]) for k in self.objects]) + i
64
+
65
+ def add(self, data):
66
+ offset = str(self.offset).rjust(10, '0')
67
+ self.offset += len(data)
68
+ self.data.append(data)
69
+ if self.xref is None:
70
+ self.xref = ['xref', '0 1', '0000000000 65535 f\r']
71
+ self.xref.append('{} 1'.format(data.split()[0]))
72
+ self.xref.append('{} 00000 n\r'.format(offset))
73
+
74
+ def page(self):
75
+ for key, offset in self.objects.items():
76
+ content = self.content[offset:offset + 500]
77
+ if b'/Page' in content and b'/Pages' not in content:
78
+ return key
79
+ raise BaseException('No page was found in the PDF')
80
+
81
+ def finalize(self):
82
+ xrefstart = str(self.offset)
83
+ data = '\n'.join(self.xref)
84
+ data += '\ntrailer\n<<\n/Size {}\n/Root {} R\n/Prev {}\n>>\n'.format(
85
+ (self.size + len(self.xref) - 5), self.root, self.startxref[-1]
86
+ )
87
+ data += 'startxref\n'
88
+ data += xrefstart
89
+ data += '\n%%EOF'
90
+ self.offset += len(data)
91
+ self.data.append(data)
92
+
93
+ def hash(self, n=0):
94
+ w, h = 900, 200
95
+ left = n * 200
96
+ signer = self.signer.split(':')[0]
97
+ stamp_file_path = self.stamp(signer)
98
+ print(stamp_file_path)
99
+ self.add(self.obj().decode().replace('>>', '/AcroForm <<\n/Fields [{} 0 R]\n/SigFlags 3\n>>\n>>'.format(self.next(1))))
100
+ self.add(self.obj(self.page()).decode().replace('/Page', '/Page /Annots [{} 0 R]'.format(self.next(1))))
101
+ a = "{} 0 obj\n<<\n/FT /Sig\n/Type /Annot\n/Subtype /Widget\n/F 132\n/T (Signature1)\n/V {} 0 R\n/P {} R\n/Rect [{} 0 {} {}]\n/AP {} 0 R\n>>\nendobj\n".format(
102
+ self.next(1), self.next(2), self.page(), w/10*2+left, left, h/10*2, self.next(3))
103
+ b = "{} 0 obj\n<<\n/Type /Sig\n/Filter /Adobe.PPKLite\n/SubFilter /adbe.pkcs7.detached\n/M ({})\n/Contents <{}>\n/ByteRange {}\n/Name ({})\n>>\nendobj\n".format(
104
+ self.next(2), datetime.now().strftime("D:%Y%m%d%H%M%S+00'00'"), '0' * SIGNATURE_SIZE, BYTERANGE, signer)
105
+ c = "{} 0 obj\n<<\n/N {} 0 R\n>>\nendobj\n".format(self.next(3), self.next(4))
106
+ stream = 'q\n{} 0 0 {} 0 0 cm\n/Img1 Do\nQ'.format(w, h)
107
+ d = "{} 0 obj\n<</Type/XObject/Subtype/Form/Resources<</XObject<</Img1 {} 0 R>>>>/BBox[0 0 {} {}]/Length {}>>\nstream\n{}\nendstream\nendobj\n".format(self.next(4), self.next(5), w, h, len(stream), stream)
108
+ x = base64.a85encode(open(stamp_file_path, 'rb').read()).decode()
109
+ e = "{} 0 obj\n<<\n/BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /DCTDecode ] /Length {} /Subtype /Image /Type /XObject /Width {} /Height {} /Resources<< >> >>\nstream\n{}\nendstream\nendobj\n".format(self.next(5), len(x), w, h, x)
110
+ self.add(a)
111
+ i = self.offset + b.index('/Contents') + 10
112
+ j = i + SIGNATURE_SIZE + 2
113
+ self.add(b)
114
+ self.add(c)
115
+ self.add(d)
116
+ self.add(e)
117
+ self.finalize()
118
+ self.byterange = [0, i, j, self.length() - j]
119
+ self.data[3] = self.data[3].replace(
120
+ BYTERANGE, '[{} {} {} {}]'.format(*self.byterange).ljust(len(BYTERANGE), ' ')
121
+ )
122
+ for data in self.data:
123
+ self.content += data.encode()
124
+ i, j, x, y = self.byterange
125
+ content = self.content[i:i+j] + self.content[x:x+y]
126
+ hash = base64.b64encode(hashlib.sha256(content).digest()).decode()
127
+ return hash
128
+
129
+ def length(self):
130
+ i = len(self.content)
131
+ for data in self.data:
132
+ i += len(data)
133
+ return i
134
+
135
+ def signed(self, name):
136
+ return '/Name ({})'.format(name).encode() in self.content
137
+
138
+ def stamp(self, name):
139
+ w, h = 900, 200
140
+ bgcolor = '#FFFFFF'
141
+ date = datetime.now()
142
+ img = Image.new('RGB', (w, h), (255, 255, 255))
143
+ img1 = ImageDraw.Draw(img)
144
+ img1.rectangle([(3, 3), (w - 3, h - 3)], fill=bgcolor, outline=bgcolor)
145
+ font = ImageFont.truetype(os.path.join('/Users/breno/Documents/Workspace/suap', 'comum', 'static/comum/font/MicrosoftSansSerif.ttf'), 25)
146
+ bold = ImageFont.truetype(os.path.join('/Users/breno/Documents/Workspace/suap', 'comum', 'static/comum/font/MicrosoftSansSerifBold.ttf'), 25)
147
+ x, y = 380, 10
148
+ img1.text((x, y), 'DOCUMENTO ASSINADO DIGITALMENTE', (0, 0, 0), font=font)
149
+ y += 45
150
+ img1.text((x, y), name, (0, 0, 0), font=bold)
151
+ y += 35
152
+ img1.text((x, y), 'Data/Hora: {}'.format(date.strftime('%d/%m/%Y %H:%M:%S')), (0, 0, 0), font=font)
153
+ y += 35
154
+ img1.text((x, y), 'Verifique em https://verificador.iti.br', (0, 0, 0), font=font)
155
+ y += 35
156
+ tmp = tempfile.NamedTemporaryFile(suffix='.jpeg', delete=False)
157
+ logo = Image.open(os.path.join(os.path.dirname(__file__), 'images', 'icp-brasil.png'))
158
+ img.paste(logo.resize((int(logo.width*0.6), int(logo.height*0.6))), (5, 10))
159
+ img = img.convert("RGB")
160
+ img.save(tmp.name, format='jpeg')
161
+ return tmp.name
162
+
163
+ def sign(self, path=None):
164
+ signature = self.sign_hash(self.hash())
165
+ path = path or '{}-signed.pdf'.format(self.path)
166
+ with open(path, 'wb') as fp:
167
+ content = self.content
168
+ if signature:
169
+ i, j, x, y = self.byterange
170
+ content = self.content[i:i + j] + b'<' + base64.b64decode(signature).hex().ljust(SIGNATURE_SIZE, '0').encode() + b'>' + self.content[x:x + y]
171
+ fp.write(content)
172
+
173
+ def sign_hash(self, hash):
174
+ return None
175
+
176
+
177
+ #curl -X POST 'https://verificador.staging.iti.br/report' --header 'Content-Type: multipart/form-data' --form 'report_type="json"' --form 'signature_files[]=@"hello-assinado.pdf"' --form 'detached_files[]=""'
@@ -0,0 +1,70 @@
1
+ from django.test import TestCase
2
+ from . import PdfWriter, VidaasPdfSigner
3
+
4
+ HTML = """
5
+ <h1>Big title</h1>
6
+ <dl>
7
+ <dt>Description title</dt>
8
+ <dd>Description Detail</dd>
9
+ </dl>
10
+ <section>
11
+ <h2>Section title</h2>
12
+ <p><b>Hello</b> world. <u>I am</u> <i>tired</i>.</p>
13
+ <p><a href="https://github.com/py-pdf/fpdf2">py-pdf/fpdf2 GitHub repo</a></p>
14
+ <p align="right">right aligned text</p>
15
+ <p>i am a paragraph <br>in two parts.</p>
16
+ <font color="#00ff00"><p>hello in green</p></font>
17
+ <font size="7"><p>hello small</p></font>
18
+ <font face="helvetica"><p>hello helvetica</p></font>
19
+ <font face="times"><p>hello times</p></font>
20
+ </section>
21
+ <section>
22
+ <h2>Other section title</h2>
23
+ <ul type="circle">
24
+ <li>unordered</li>
25
+ <li>list</li>
26
+ <li>items</li>
27
+ </ul>
28
+ <ol start="3" type="i">
29
+ <li>ordered</li>
30
+ <li>list</li>
31
+ <li>items</li>
32
+ </ol>
33
+ <br>
34
+ <br>
35
+ <pre>i am preformatted text.</pre>
36
+ <br>
37
+ <blockquote>hello blockquote</blockquote>
38
+ <table width="50%">
39
+ <thead>
40
+ <tr>
41
+ <th width="30%">ID</th>
42
+ <th width="70%">Name</th>
43
+ </tr>
44
+ </thead>
45
+ <tbody>
46
+ <tr>
47
+ <td>1</td>
48
+ <td>Alice</td>
49
+ </tr>
50
+ <tr>
51
+ <td>2</td>
52
+ <td>Bob</td>
53
+ </tr>
54
+ </tbody>
55
+ </table>
56
+ </section>
57
+ """
58
+
59
+ class AnimalTestCase(TestCase):
60
+ def setUp(self):
61
+ return super().setUp()
62
+
63
+ def test_pdf(self):
64
+ writter = PdfWriter(HTML)
65
+ writter.save('test4.pdf')
66
+ signer = VidaasPdfSigner('test4.pdf', 'Carlos Breno Pereira Silva:04770402414')
67
+ signer.sign()
68
+
69
+ def tearDown(self):
70
+ return super().tearDown()
@@ -78,6 +78,7 @@ class SeleniumTestCase(LiveServerTestCase):
78
78
  if os.path.exists(fixture_path):
79
79
  call_command("loaddata", fixture_path)
80
80
  settings.DEBUG = True
81
+ settings.SITE_URL = cls.live_server_url
81
82
 
82
83
  def create_superuser(self, username, password):
83
84
  if not User.objects.filter(username=username).exists():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: slthcore
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: API generator based on yml file
5
5
  Home-page: https://github.com/brenokcc
6
6
  Author: Breno Silva
@@ -61,6 +61,8 @@ slth/migrations/0005_alter_profile_photo.py
61
61
  slth/migrations/0006_user.py
62
62
  slth/migrations/0007_deletion_log.py
63
63
  slth/migrations/__init__.py
64
+ slth/pdf/__init__.py
65
+ slth/pdf/tests.py
64
66
  slth/selenium/__init__.py
65
67
  slth/selenium/browser.py
66
68
  slth/static/.DS_Store
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes