def test_file_creator08(self): "Secure filename" dir_path = self.dir_path fcreator = FileCreator(dir_path, 'foo bar.txt', generators=[IncrFileNameSuffixGenerator]) path1 = fcreator.create() self.assertEqual(join(dir_path, 'foo_bar.txt'), path1)
def test_file_creator07(self): "Max length (length too short for extension...)" dir_path = self.dir_path fcreator = FileCreator(dir_path, 'foobar.txt', generators=[DateFileNameSuffixGenerator], max_length=3) with self.assertRaises(FileCreator.Error): fcreator.create()
def test_file_creator09(self): "Default 'generators' argument" dir_path = self.dir_path fcreator = FileCreator(dir_path, 'foobar.txt') path1 = fcreator.create() with self.assertNoException(): path2 = fcreator.create() self.assertNotEqual(path1, path2)
def test_file_creator01(self): "With 1 generator (IncrFileNameGenerator)" dir_path = self.dir_path name1 = 'foobar.txt' fcreator = FileCreator(dir_path, name1, generators=[IncrFileNameSuffixGenerator]) path1 = fcreator.create() self.assertTrue(exists(dir_path)) self.assertEqual([name1], listdir(dir_path)) self.assertEqual(join(dir_path, name1), path1) path2 = fcreator.create() name2 = 'foobar_1.txt' self.assertEqual({name1, name2}, set(listdir(dir_path))) self.assertEqual(join(dir_path, name2), path2)
def test_create(self): "Auto-fill title if empty." from creme.creme_core.utils.file_handling import FileCreator filename = 'DocTestCreate001.txt' final_path = FileCreator( dir_path=join(settings.MEDIA_ROOT, 'upload', 'documents'), name=filename, max_length=Document._meta.get_field('filedata').max_length, ).create() user = self.create_user() folder = Folder.objects.all()[0] title = 'Test doc' doc1 = Document.objects.create( user=user, title=title, linked_folder=folder, filedata=final_path, ) self.assertEqual(title, doc1.title) doc2 = Document.objects.create( user=user, linked_folder=folder, filedata=final_path, ) self.assertEqual(filename, doc2.title)
def _create_file(name): rel_media_dir_path = join('upload', 'creme_core-tests', 'models') final_path = FileCreator(join(settings.MEDIA_ROOT, rel_media_dir_path), name).create() with open(final_path, 'w') as f: f.write('I am the content') return join(rel_media_dir_path, basename(final_path))
def _create_file_for_tempfile(self, name): rel_media_dir_path = join('upload', 'creme_core-tests') abs_path = FileCreator( dir_path=join(settings.MEDIA_ROOT, rel_media_dir_path), name=name, ).create() with open(abs_path, 'w') as f: f.write('I am the content') return abs_path, join(rel_media_dir_path, basename(abs_path))
def test_file_creator02(self): "With 1 generator (DateFileNameGenerator)." dir_path = self.dir_path name1 = 'stuff.txt' fcreator = FileCreator( dir_path, name1, generators=[DateFileNameSuffixGenerator], ) fcreator.create() self.assertEqual([name1], listdir(dir_path)) fcreator.create() name2 = 'stuff_{}.txt'.format(date.today().strftime('%d%m%Y')) self.assertSetEqual({name1, name2}, {*listdir(dir_path)}) with self.assertRaises(FileCreator.Error): fcreator.create()
def test_file_creator06(self): "Max length (suffix is too long even alone)" dir_path = self.dir_path name = 'foobar.txt' # len == 10 fcreator = FileCreator(dir_path, name, generators=[DateFileNameSuffixGenerator], max_length=12) fcreator.create() with self.assertRaises(FileCreator.Error): fcreator.create()
def test_file_creator02(self): "With 1 generator (DateFileNameGenerator)" dir_path = self.dir_path name1 = 'stuff.txt' fcreator = FileCreator(dir_path, name1, generators=[DateFileNameSuffixGenerator], ) fcreator.create() self.assertEqual([name1], listdir(dir_path)) fcreator.create() date_str = date.today().strftime('%d%m%Y') name2 = 'stuff_%s.txt' % date_str self.assertEqual({name1, name2}, set(listdir(dir_path))) with self.assertRaises(FileCreator.Error): fcreator.create()
def test_file_creator04(self): "Max trials" dir_path = self.dir_path name1 = 'foobar.txt' fcreator = FileCreator(dir_path, name1, generators=[IncrFileNameSuffixGenerator], max_trials=2) fcreator.create() fcreator.create() with self.assertRaises(FileCreator.Error): fcreator.create()
def test_file_creator05(self): "Max length" dir_path = self.dir_path name = 'foobar.txt' # len == 10 fcreator = FileCreator(dir_path, name, generators=[DateFileNameSuffixGenerator], max_length=15) fcreator.create() fcreator.create() self.assertEqual({name, 'fo_{}.txt'.format(date.today().strftime('%d%m%Y')) }, set(listdir(dir_path)) )
def test_file_creator03(self): "2 generators" dir_path = self.dir_path name1 = 'stuff.txt' fcreator = FileCreator(dir_path, name1, generators=(DateFileNameSuffixGenerator, IncrFileNameSuffixGenerator, ), ) fcreator.create() self.assertEqual([name1], listdir(dir_path)) fcreator.create() date_str = date.today().strftime('%d%m%Y') name2 = 'stuff_%s.txt' % date_str self.assertEqual({name1, name2}, set(listdir(dir_path))) fcreator.create() name3 = 'stuff_%s_1.txt' % date_str self.assertEqual({name1, name2, name3}, set(listdir(dir_path)))
def export(self, entity, user): html_template = get_template(self.html_template_path) css_template = get_template(self.css_template_path) context = self.get_context_data(object=entity) with override(language=self.flavour.language): html_content = html_template.render(context) css_content = css_template.render(context) # NB: before creating file to raise error as soon a possible # & avoid junk files. html = HTML(string=html_content) css = CSS(string=css_content) basename = secure_filename( f'{entity._meta.verbose_name}_{entity.id}.pdf') final_path = FileCreator( dir_path=path.join(settings.MEDIA_ROOT, 'upload', 'billing'), name=basename, ).create() # NB: we create the FileRef instance as soon as possible to get the # smallest duration when a crash causes a file which have to be # removed by hand (not cleaned by the Cleaner job). file_ref = FileRef.objects.create( user=user, filedata=f'upload/billing/{path.basename(final_path)}', basename=basename, ) # TODO ? # from weasyprint.fonts import FontConfiguration # font_config = FontConfiguration() html.write_pdf( final_path, stylesheets=[css], # TODO: ??? # font_config=font_config ) return file_ref
def export(self, entity, user): writer = self.get_writer(entity, user) basename = secure_filename( f'{entity._meta.verbose_name}_{entity.id}.xls') final_path = FileCreator( dir_path=path.join(settings.MEDIA_ROOT, 'upload', 'billing'), name=basename, ).create() # NB: we create the FileRef instance as soon as possible to get the # smallest duration when a crash causes a file which have to be # removed by hand (not cleaned by the Cleaner job). file_ref = FileRef.objects.create( user=user, filedata='upload/billing/' + path.basename(final_path), basename=basename, ) writer.save(final_path) return file_ref
def generate_pdf(self, *, content, dir_path, basename): latex_file_path = path.join(dir_path, f'{basename}.tex') # NB: we precise the encoding or it oddly crashes on some systems... with open(latex_file_path, 'w', encoding='utf-8') as f: f.write(smart_str(content)) # NB: return code seems always 1 even when there is no error... subprocess.call([ 'pdflatex', '-interaction=batchmode', '-output-directory', dir_path, latex_file_path, ]) pdf_basename = f'{basename}.pdf' temp_pdf_file_path = path.join(dir_path, pdf_basename) if not path.exists(temp_pdf_file_path): logger.critical( 'It seems the PDF generation has failed. ' 'The temporary directory has not been removed, ' 'so you can inspect the *.log file in "%s"', dir_path, ) # TODO: use a better exception class ? raise ConflictError( _('The generation of the PDF file has failed ; ' 'please contact your administrator.')) final_path = FileCreator( dir_path=path.join(settings.MEDIA_ROOT, 'upload', 'billing'), name=pdf_basename, ).create() copy(temp_pdf_file_path, final_path) return final_path, pdf_basename
def create_uploaded_file(*, file_name: str, dir_name: str, content: Union[str, List[str]] = 'I am the content'): from os import path as os_path from shutil import copy from creme.creme_core.utils.file_handling import FileCreator rel_media_dir_path = os_path.join('upload', 'creme_core-tests', dir_name) final_path = FileCreator( os_path.join(settings.MEDIA_ROOT, rel_media_dir_path), file_name, ).create() if isinstance(content, list): copy(os_path.join(*content), final_path) elif isinstance(content, str): with open(final_path, 'w') as f: f.write(content) return os_path.join(rel_media_dir_path, os_path.basename(final_path))
def export_as_pdf(request, base_id): entity = get_object_or_404(CremeEntity, pk=base_id).get_real_entity() has_perm = request.user.has_perm_to_view_or_die has_perm(entity) template_path = TEMPLATE_PATHS.get(entity.__class__) if template_path is None: raise ConflictError('This type of entity cannot be exported as pdf') source = entity.get_source().get_real_entity() has_perm(source) target = entity.get_target().get_real_entity() has_perm(target) document_name = str(entity._meta.verbose_name) template = loader.get_template(template_path) context = { 'plines': entity.get_lines(billing.get_product_line_model()), 'slines': entity.get_lines(billing.get_service_line_model()), 'source': source, 'target': target, 'object': entity, 'document_name': document_name, } basename = secure_filename('{}_{}'.format(document_name, entity.id)) tmp_dir_path = mkdtemp(prefix='creme_billing_latex') latex_file_path = path.join(tmp_dir_path, '{}.tex'.format(basename)) # NB: we precise the encoding or it oddly crashes on some systems... with open(latex_file_path, 'w', encoding='utf-8') as f: f.write(smart_str(template.render(context))) # NB: return code seems always 1 even when there is no error... subprocess.call([ 'pdflatex', '-interaction=batchmode', '-output-directory', tmp_dir_path, latex_file_path, ]) pdf_basename = '{}.pdf'.format(basename) temp_pdf_file_path = path.join(tmp_dir_path, pdf_basename) if not path.exists(temp_pdf_file_path): logger.critical( 'It seems the PDF generation has failed. ' 'The temporary directory has not been removed, ' 'so you can inspect the *.log file in "%s"', tmp_dir_path) # TODO: use a better exception class ? raise ConflictError( _('The generation of the PDF file has failed ; please contact your administrator.' )) final_path = FileCreator( dir_path=path.join(settings.MEDIA_ROOT, 'upload', 'billing'), name=pdf_basename, ).create() copy(temp_pdf_file_path, final_path) rmtree(tmp_dir_path) fileref = FileRef.objects.create( # user=request.user, TODO filedata='upload/billing/' + path.basename(final_path), basename=pdf_basename, ) return HttpResponseRedirect( reverse( 'creme_core__dl_file', args=(fileref.filedata, ), ))
def generate_png(self, user): from os.path import join import pygraphviz as pgv # NB: to work with utf8 label in node: all node must be added explicitly with # unicode label, and when edges are a created, nodes identified by their # labels encoded as string graph = pgv.AGraph(directed=True) # NB: "self.roots.all()" causes a strange additional query (retrieving of the base CremeEntity !).... has_perm_to_view = user.has_perm_to_view roots = [ root for root in RootNode.objects.filter( graph=self.id).select_related('entity') if not root.entity.is_deleted and has_perm_to_view(root.entity) ] add_node = graph.add_node add_edge = graph.add_edge # TODO: entity cache ? regroups relations by type ? ... CremeEntity.populate_real_entities([root.entity for root in roots ]) #small optimisation for root in roots: add_node(str(root.entity), shape='box') # add_node('filled box', shape='box', style='filled', color='#FF00FF') # add_node('filled box v2', shape='box', style='filled', fillcolor='#FF0000', color='#0000FF', penwidth='2.0') #default pensize="1.0" orbital_nodes = {} #cache for root in roots: subject = root.entity str_subject = str(subject) relations = subject.relations.filter(type__in=root.relation_types.all())\ .select_related('object_entity', 'type') Relation.populate_real_object_entities( relations) # Small optimisation for relation in relations: object_ = relation.object_entity if not user.has_perm_to_view(object_): continue uni_object = str(object_) str_object = uni_object orbital_node = orbital_nodes.get(object_.id) if not orbital_node: add_node(uni_object) orbital_nodes[object_.id] = str_object add_edge(str_subject, str_object, label=str(relation.type.predicate)) # add_edge('b', 'd', color='#FF0000', fontcolor='#00FF00', label='foobar', style='dashed') orbital_rtypes = self.orbital_relation_types.all() if orbital_rtypes: orbital_ids = orbital_nodes.keys() for relation in Relation.objects.filter( subject_entity__in=orbital_ids, object_entity__in=orbital_ids, type__in=orbital_rtypes).select_related('type'): add_edge(orbital_nodes[relation.subject_entity_id], orbital_nodes[relation.object_entity_id], label=str(relation.type.predicate), style='dashed') # print graph.string() graph.layout(prog='dot') # Algo: neato dot twopi circo fdp nop img_format = 'png' # Format: pdf svg img_basename = 'graph_{}.{}'.format(self.id, img_format) try: path = FileCreator(join(settings.MEDIA_ROOT, 'upload', 'graphs'), img_basename).create() except FileCreator.Error as e: raise self.GraphException(e) from e try: # graph.draw(join(dir_path, filename), format='png') # Format: pdf svg graph.draw(path, format=img_format) # Format: pdf svg except IOError as e: delete_file(path) raise self.GraphException(str(e)) from e fileref = FileRef.objects.create( # user=request.user, TODO filedata='upload/graphs/' + basename(path), basename=img_basename, ) return HttpResponseRedirect( reverse('creme_core__dl_file', args=(fileref.filedata, )))