Source code for mathmaker.lib.core.base

# -*- coding: utf-8 -*-

# Mathmaker creates automatically maths exercises sheets
# with their answers
# Copyright 2006-2017 Nicolas Hainaux <nh.techn@gmail.com>

# This file is part of Mathmaker.

# Mathmaker is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# any later version.

# Mathmaker is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with Mathmaker; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import subprocess
from abc import ABCMeta, abstractmethod

from mathmaker import settings
from mathmaker.lib.tools import generate_preamble_comment


# ------------------------------------------------------------------------------
# --------------------------------------------------------------------------
# ------------------------------------------------------------------------------
##
# @class Clonable
# @brief All objects that are used must be able to be copied deeply
# Any Clonable are provided the clone() method, no need to reimplement it
[docs]class Clonable(object): # -------------------------------------------------------------------------- ## # @brief Returns a deep copy of the object
[docs] def clone(self): result = object.__new__(type(self)) result.__init__(self) return result
# ------------------------------------------------------------------------------ # -------------------------------------------------------------------------- # ------------------------------------------------------------------------------ ## # @class NamedObject # @brief Abstract mother class of objects having a name
[docs]class NamedObject(Clonable, metaclass=ABCMeta): # -------------------------------------------------------------------------- ## # @brief Constructor # @warning Must be redefined @abstractmethod def __init__(self): pass # -------------------------------------------------------------------------- ## # @brief Returns the name of the object @property def name(self): return self._name # -------------------------------------------------------------------------- ## # @brief Sets the name of the object @name.setter def name(self, arg): if not (type(arg) == str or type(arg) == int): raise ValueError('Got: ' + str(type(arg)) + 'instead of str|int') self._name = str(arg)
# ------------------------------------------------------------------------------ # -------------------------------------------------------------------------- # ------------------------------------------------------------------------------ ## # @class Printable # @brief All Printable objects: Exponenteds & others (Equations...) # Any Printable must reimplement the into_str() method
[docs]class Printable(NamedObject, metaclass=ABCMeta): # -------------------------------------------------------------------------- ## # @brief Creates a string of the given object in the given ML # @param options Any options # @return The formated string
[docs] @abstractmethod def into_str(self, **options): pass
@property def printed(self): """ Shortcut for self.into_str(force_expression_begins=True) This returns the string of the Printable object, assuming it starts the expression. """ return self.into_str(force_expression_begins=True) @property def jsprinted(self): """ Shortcut for self.into_str(force_expression_begins=True, js_repr=True) This returns the string of the Printable object, assuming it starts the expression. """ return self.into_str(force_expression_begins=True, js_repr=True)
# ------------------------------------------------------------------------------ # -------------------------------------------------------------------------- # ------------------------------------------------------------------------------ ## # @class Drawable # @brief All Drawable objects. Any Drawable must reimplement into_euk() # Drawable are not renamable
[docs]class Drawable(NamedObject, metaclass=ABCMeta): # -------------------------------------------------------------------------- ## # @brief Returns the eukleides filename associated to the triangle @property def euk_filename(self): return self.filename + ".euk" # -------------------------------------------------------------------------- ## # @brief Returns the eps filename associated to the triangle @property def eps_filename(self): return self.filename + ".eps" # -------------------------------------------------------------------------- ## # @brief Returns the name of the object @property def name(self): return self._name # -------------------------------------------------------------------------- ## # @brief Prevents Drawable objects from being renamed, since they get # their name from other properties inside them. @name.setter def name(self, arg): raise RuntimeError('Impossible to rename this object') # -------------------------------------------------------------------------- ## # @brief Creates the euk string to put in the file # @param options Any options # @return The string to put in the picture file
[docs] @abstractmethod def into_euk(self): pass
# -------------------------------------------------------------------------- ## # @brief Creates the picture of the drawable object # @return Nothing, just creates the picture file
[docs] def into_pic(self, create_pic_file=True): hc = generate_preamble_comment('eukleides') if create_pic_file: euk_path = settings.outputdir + self.euk_filename with open(euk_path, 'w') as f: f.write(hc + self.into_euk()) # todo: remove the options when they are corrected in euktoeps p = subprocess.Popen([settings.euktoeps, '-i', r'\usepackage{eukleides,graphicx,textcomp}', euk_path], cwd=settings.outputdir) p.wait()