diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..b8919f6 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,28 @@ +# .coveragerc to control coverage.py +[run] +branch = True +source = tutorial_canciones +# omit = bad_file.py + +[paths] +source = + src/ + */site-packages/ + +[report] +# Regexes for lines to exclude from consideration +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about missing debug-only code: + def __repr__ + if self\.debug + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError + + # Don't complain if non-runnable code isn't run: + if 0: + if __name__ == .__main__.: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b86eb24 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +.idea/* +src/modelo/__pycache__/* +src/logica/__pycache__/* diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..e749d6b --- /dev/null +++ b/.pylintrc @@ -0,0 +1 @@ +extension-pkg-whitelist=PyQt5 \ No newline at end of file diff --git a/AUTHORS.rst b/AUTHORS.rst new file mode 100644 index 0000000..844ee1b --- /dev/null +++ b/AUTHORS.rst @@ -0,0 +1,5 @@ +============ +Contributors +============ + +* Dayana diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..226e6f5 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,10 @@ +========= +Changelog +========= + +Version 0.1 +=========== + +- Feature A added +- FIX: nasty bug #1729 fixed +- add your changes here! diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..ee12693 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 Dayana + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5fe4739 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# TutorialCanciones diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..8913ecf --- /dev/null +++ b/README.rst @@ -0,0 +1,19 @@ +================== +tutorial_canciones +================== + + +Add a short description here! + + +Description +=========== + +A longer description of your project goes here... + + +Note +==== + +This project has been set up using PyScaffold 3.2.3. For details and usage +information on PyScaffold see https://pyscaffold.org/. diff --git a/aplicacion.sqlite b/aplicacion.sqlite new file mode 100644 index 0000000..ee0a4d6 Binary files /dev/null and b/aplicacion.sqlite differ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..0224d2a --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,193 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = ../build/sphinx/ +AUTODOCDIR = api +AUTODOCBUILD = sphinx-apidoc +PROJECT = tutorial_canciones +MODULEDIR = ../src/tutorial_canciones + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext doc-requirements + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* $(AUTODOCDIR) + +$(AUTODOCDIR): $(MODULEDIR) + mkdir -p $@ + $(AUTODOCBUILD) -f -o $@ $^ + +doc-requirements: $(AUTODOCDIR) + +html: doc-requirements + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: doc-requirements + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: doc-requirements + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: doc-requirements + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: doc-requirements + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: doc-requirements + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: doc-requirements + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/$(PROJECT).qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/$(PROJECT).qhc" + +devhelp: doc-requirements + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $HOME/.local/share/devhelp/$(PROJECT)" + @echo "# ln -s $(BUILDDIR)/devhelp $HOME/.local/share/devhelp/$(PROJEC)" + @echo "# devhelp" + +epub: doc-requirements + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +patch-latex: + find _build/latex -iname "*.tex" | xargs -- \ + sed -i'' 's~includegraphics{~includegraphics\[keepaspectratio,max size={\\textwidth}{\\textheight}\]{~g' + +latex: doc-requirements + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(MAKE) patch-latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: doc-requirements + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(MAKE) patch-latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: doc-requirements + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: doc-requirements + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: doc-requirements + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: doc-requirements + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: doc-requirements + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: doc-requirements + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: doc-requirements + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: doc-requirements + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: doc-requirements + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: doc-requirements + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: doc-requirements + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/authors.rst b/docs/authors.rst new file mode 100644 index 0000000..cd8e091 --- /dev/null +++ b/docs/authors.rst @@ -0,0 +1,2 @@ +.. _authors: +.. include:: ../AUTHORS.rst diff --git a/docs/changelog.rst b/docs/changelog.rst new file mode 100644 index 0000000..871950d --- /dev/null +++ b/docs/changelog.rst @@ -0,0 +1,2 @@ +.. _changes: +.. include:: ../CHANGELOG.rst diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..7bd6f9f --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,272 @@ +# -*- coding: utf-8 -*- +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import os +import sys +import inspect +import shutil + +__location__ = os.path.join(os.getcwd(), os.path.dirname( + inspect.getfile(inspect.currentframe()))) + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.join(__location__, '../src')) + +# -- Run sphinx-apidoc ------------------------------------------------------ +# This hack is necessary since RTD does not issue `sphinx-apidoc` before running +# `sphinx-build -b html . _build/html`. See Issue: +# https://github.com/rtfd/readthedocs.org/issues/1139 +# DON'T FORGET: Check the box "Install your project inside a virtualenv using +# setup.py install" in the RTD Advanced Settings. +# Additionally it helps us to avoid running apidoc manually + +try: # for Sphinx >= 1.7 + from sphinx.ext import apidoc +except ImportError: + from sphinx import apidoc + +output_dir = os.path.join(__location__, "api") +module_dir = os.path.join(__location__, "../src/modelo") +try: + shutil.rmtree(output_dir) +except FileNotFoundError: + pass + +try: + import sphinx + from pkg_resources import parse_version + + cmd_line_template = "sphinx-apidoc -f -o {outputdir} {moduledir}" + cmd_line = cmd_line_template.format(outputdir=output_dir, moduledir=module_dir) + + args = cmd_line.split(" ") + if parse_version(sphinx.__version__) >= parse_version('1.7'): + args = args[1:] + + apidoc.main(args) +except Exception as e: + print("Running `sphinx-apidoc` failed!\n{}".format(e)) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', + 'sphinx.ext.autosummary', 'sphinx.ext.viewcode', 'sphinx.ext.coverage', + 'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax', + 'sphinx.ext.napoleon'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'modelo' +copyright = u'2020, Dayana' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '' # Is set by calling `setup.py docs` +# The full version, including alpha/beta/rc tags. +release = '' # Is set by calling `setup.py docs` + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { + 'sidebar_width': '300px', + 'page_width': '1200px' +} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +try: + from tutorial_canciones import __version__ as version +except ImportError: + pass +else: + release = version + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = "" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'modelo-doc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +# 'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +# 'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +# 'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'user_guide.tex', u'modelo Documentation', + u'Dayana', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = "" + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + +# -- External mapping ------------------------------------------------------------ +python_version = '.'.join(map(str, sys.version_info[0:2])) +intersphinx_mapping = { + 'sphinx': ('http://www.sphinx-doc.org/en/stable', None), + 'python': ('https://docs.python.org/' + python_version, None), + 'matplotlib': ('https://matplotlib.org', None), + 'numpy': ('https://docs.scipy.org/doc/numpy', None), + 'sklearn': ('http://scikit-learn.org/stable', None), + 'pandas': ('http://pandas.pydata.org/pandas-docs/stable', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/reference', None), +} diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..63031d7 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,59 @@ +================== +tutorial_canciones +================== + +This is the documentation of **tutorial_canciones**. + +.. note:: + + This is the main page of your project's `Sphinx`_ documentation. + It is formatted in `reStructuredText`_. Add additional pages + by creating rst-files in ``docs`` and adding them to the `toctree`_ below. + Use then `references`_ in order to link them from this page, e.g. + :ref:`authors` and :ref:`changes`. + + It is also possible to refer to the documentation of other Python packages + with the `Python domain syntax`_. By default you can reference the + documentation of `Sphinx`_, `Python`_, `NumPy`_, `SciPy`_, `matplotlib`_, + `Pandas`_, `Scikit-Learn`_. You can add more by extending the + ``intersphinx_mapping`` in your Sphinx's ``conf.py``. + + The pretty useful extension `autodoc`_ is activated by default and lets + you include documentation from docstrings. Docstrings can be written in + `Google style`_ (recommended!), `NumPy style`_ and `classical style`_. + + +Contents +======== + +.. toctree:: + :maxdepth: 2 + + License + Authors + Changelog + Module Reference + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. _toctree: http://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html +.. _reStructuredText: http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html +.. _references: http://www.sphinx-doc.org/en/stable/markup/inline.html +.. _Python domain syntax: http://sphinx-doc.org/domains.html#the-python-domain +.. _Sphinx: http://www.sphinx-doc.org/ +.. _Python: http://docs.python.org/ +.. _Numpy: http://docs.scipy.org/doc/numpy +.. _SciPy: http://docs.scipy.org/doc/scipy/reference/ +.. _matplotlib: https://matplotlib.org/contents.html# +.. _Pandas: http://pandas.pydata.org/pandas-docs/stable +.. _Scikit-Learn: http://scikit-learn.org/stable +.. _autodoc: http://www.sphinx-doc.org/en/stable/ext/autodoc.html +.. _Google style: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings +.. _NumPy style: https://numpydoc.readthedocs.io/en/latest/format.html +.. _classical style: http://www.sphinx-doc.org/en/stable/domains.html#info-field-lists diff --git a/docs/license.rst b/docs/license.rst new file mode 100644 index 0000000..3989c51 --- /dev/null +++ b/docs/license.rst @@ -0,0 +1,7 @@ +.. _license: + +======= +License +======= + +.. include:: ../LICENSE.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3ce41f4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,17 @@ +# ============================================================================= +# DEPRECATION WARNING: +# +# The file `requirements.txt` does not influence the package dependencies and +# will not be automatically created in the next version of PyScaffold (v4.x). +# +# Please have look at the docs for better alternatives +# (`Dependency Management` section). +# ============================================================================= +# +# Add your pinned requirements so that they can be easily installed with: +# pip install -r requirements.txt +# Remember to also add them in setup.cfg but unpinned. +# Example: +# numpy==1.13.3 +# scipy==1.0 +# diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..e28f4a7 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,115 @@ +# This file is used to configure your project. +# Read more about the various options under: +# http://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files + +[metadata] +name = tutorial_canciones +description = Add a short description here! +author = Dayana +author-email = id.romero556@uniandes.edu.co +license = mit +long-description = file: README.rst +long-description-content-type = text/x-rst; charset=UTF-8 +url = https://github.com/pyscaffold/pyscaffold/ +project-urls = + Documentation = https://pyscaffold.org/ +# Change if running only on Windows, Mac or Linux (comma-separated) +platforms = any +# Add here all kinds of additional classifiers as defined under +# https://pypi.python.org/pypi?%3Aaction=list_classifiers +classifiers = + Development Status :: 4 - Beta + Programming Language :: Python + +[options] +zip_safe = False +packages = find: +include_package_data = True +package_dir = + =src +# DON'T CHANGE THE FOLLOWING LINE! IT WILL BE UPDATED BY PYSCAFFOLD! +setup_requires = pyscaffold>=3.2a0,<3.3a0 +# Add here dependencies of your project (semicolon/line-separated), e.g. +# install_requires = numpy; scipy +# The usage of test_requires is discouraged, see `Dependency Management` docs +# tests_require = pytest; pytest-cov +# Require a specific Python version, e.g. Python 2.7 or >= 3.4 +# python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* + +[options.packages.find] +where = src +exclude = + tests + +[options.extras_require] +# Add here additional requirements for extra features, to install with: +# `pip install tutorial_canciones[PDF]` like: +# PDF = ReportLab; RXP +# Add here test requirements (semicolon/line-separated) +testing = + pytest + pytest-cov + +[options.entry_points] +# Add here console scripts like: +# console_scripts = +# script_name = tutorial_canciones.module:function +# For example: +# console_scripts = +# fibonacci = tutorial_canciones.skeleton:run +# And any other entry points, for example: +# pyscaffold.cli = +# awesome = pyscaffoldext.awesome.extension:AwesomeExtension + +[test] +# py.test options when running `python setup.py test` +# addopts = --verbose +extras = True + +[tool:pytest] +# Options for py.test: +# Specify command line options as you would do when invoking py.test directly. +# e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml +# in order to write a coverage file that can be read by Jenkins. +addopts = + --cov tutorial_canciones --cov-report term-missing + --verbose +norecursedirs = + dist + build + .tox +testpaths = tests + +[aliases] +dists = bdist_wheel + +[bdist_wheel] +# Use this option if your package is pure-python +universal = 1 + +[build_sphinx] +source_dir = docs +build_dir = build/sphinx + +[devpi:upload] +# Options for the devpi: PyPI server and packaging tool +# VCS export must be deactivated since we are using setuptools-scm +no-vcs = 1 +formats = bdist_wheel + +[flake8] +# Some sane defaults for the code style checker flake8 +exclude = + .tox + build + dist + .eggs + docs/conf.py + +[pyscaffold] +# PyScaffold's parameters when the project was created. +# This will be used when updating. Do not change! +version = 3.2.3 +package = tutorial_canciones +extensions = + no_skeleton diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1f21587 --- /dev/null +++ b/setup.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +""" + Setup file for modelo. + Use setup.cfg to configure your project. + + This file was generated with PyScaffold 3.2.3. + PyScaffold helps you to put up the scaffold of your new Python project. + Learn more under: https://pyscaffold.org/ +""" +import sys + +from pkg_resources import VersionConflict, require +from setuptools import setup + +try: + require('setuptools>=38.3') +except VersionConflict: + print("Error: version of setuptools is too old (<38.3)!") + sys.exit(1) + + +if __name__ == "__main__": + setup(use_pyscaffold=True) diff --git a/src/modelo/__init__.py b/src/modelo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/modelo/album.py b/src/modelo/album.py new file mode 100644 index 0000000..7ec1b06 --- /dev/null +++ b/src/modelo/album.py @@ -0,0 +1,23 @@ +import enum + +from sqlalchemy import Column, Integer, String, Enum +from sqlalchemy.orm import relationship + +from .declarative_base import Base + + +class Medio(enum.Enum): + DISCO = 1 + CASETE = 2 + CD = 3 + + +class Album(Base): + __tablename__ = 'album' + + id = Column(Integer, primary_key=True) + titulo = Column(String) + ano = Column(Integer) + descripcion = Column(String) + medio = Column(Enum(Medio)) + canciones = relationship('Cancion', secondary='album_cancion') diff --git a/src/modelo/cancion.py b/src/modelo/cancion.py new file mode 100644 index 0000000..71918b4 --- /dev/null +++ b/src/modelo/cancion.py @@ -0,0 +1,30 @@ +from sqlalchemy import Column, Integer, String, ForeignKey +from sqlalchemy.orm import relationship + +from .declarative_base import Base + + +class Cancion(Base): + __tablename__ = 'cancion' + + id = Column(Integer, primary_key=True) + titulo = Column(String) + minutos = Column(Integer) + segundos = Column(Integer) + compositor = Column(String) + albumes = relationship('Album', secondary='album_cancion') + interpretes = relationship('Interprete', cascade='all, delete, delete-orphan') + + +class AlbumCancion(Base): + __tablename__ = 'album_cancion' + + cancion_id = Column( + Integer, + ForeignKey('cancion.id'), + primary_key=True) + + album_id = Column( + Integer, + ForeignKey('album.id'), + primary_key=True) diff --git a/src/modelo/declarative_base.py b/src/modelo/declarative_base.py new file mode 100644 index 0000000..634427a --- /dev/null +++ b/src/modelo/declarative_base.py @@ -0,0 +1,9 @@ +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +engine = create_engine('sqlite:///aplicacion.sqlite') +Session = sessionmaker(bind=engine) + +Base = declarative_base() +session = Session() diff --git a/src/modelo/interprete.py b/src/modelo/interprete.py new file mode 100644 index 0000000..502f22b --- /dev/null +++ b/src/modelo/interprete.py @@ -0,0 +1,12 @@ +from sqlalchemy import Column, Integer, String, ForeignKey + +from .declarative_base import Base + + +class Interprete(Base): + __tablename__ = 'interprete' + + id = Column(Integer, primary_key=True) + nombre = Column(String) + texto_curiosidades = Column(String) + cancion = Column(Integer, ForeignKey('cancion.id')) diff --git a/tests/test_album.py b/tests/test_album.py new file mode 100644 index 0000000..1409924 --- /dev/null +++ b/tests/test_album.py @@ -0,0 +1,48 @@ +import unittest + +from src.logica.Coleccion import Coleccion +from src.modelo.album import Album +from src.modelo.declarative_base import Session + + +class AlbumTestCase(unittest.TestCase): + + def setUp(self): + self.session = Session() + self.coleccion = Coleccion() + + def testAgregarAlbum(self): + self.coleccion.agregarAlbum("Mio", 2000, "Sin descripción", "CD") + self.coleccion.agregarAlbum("Clara luna", 1992, "Sin descripción", "CASETE") + self.consulta1 = self.session.query(Album).filter(Album.titulo == "Mio").first() + self.consulta2 = self.session.query(Album).filter(Album.id == 2).first() + self.assertEqual(self.consulta1.titulo, "Mio") + self.assertIsNotNone(self.consulta2) + + def testEditarAlbum(self): + self.coleccion.editarAlbum(2, "Clara luna-Mix", 1982, "Sin descripción", "DISCO") + self.consulta = self.session.query(Album).filter(Album.id == 2).first() + self.assertIsNot(self.consulta.titulo, "Clara luna") + + def testEliminarAlbum(self): + self.coleccion.eliminarAlbum(1) + self.consulta = self.session.query(Album).filter(Album.id == 1).first() + self.assertIsNone(self.consulta) + + def testBuscarAlbumesPorTitulo(self): + self.consulta1 = self.coleccion.buscarAlbumesPorTitulo("clara luna") + self.coleccion.agregarAlbum("Clara luna-Instrumental", 1992, "Sin descripción", "CD") + self.consulta2 = self.coleccion.buscarAlbumesPorTitulo("clara luna") + self.assertGreater(len(self.consulta2), len(self.consulta1)) + + def testDarAlbumPorId(self): + self.coleccion.agregarAlbum("Infinito arcoiris", 1990, "Sin descripción", "CASETE") + self.album_id = self.session.query(Album).filter(Album.titulo == "Infinito arcoiris").first().id + self.consulta = self.coleccion.darAlbumPorId(self.album_id)["titulo"] + self.assertEqual(self.consulta, "Infinito arcoiris") + + def testDarAlbumes(self): + self.consulta1 = self.coleccion.darAlbumes() + self.coleccion.agregarAlbum("New life", 2018, "Album escrito para...", "CD") + self.consulta2 = self.coleccion.darAlbumes() + self.assertGreater(len(self.consulta2), len(self.consulta1)) diff --git a/tests/test_cancion.py b/tests/test_cancion.py new file mode 100644 index 0000000..b0c9925 --- /dev/null +++ b/tests/test_cancion.py @@ -0,0 +1,83 @@ +import unittest + +from src.logica.Coleccion import Coleccion +from src.modelo.album import Album +from src.modelo.cancion import Cancion +from src.modelo.declarative_base import Session +from src.modelo.interprete import Interprete + + +class CancionTestCase(unittest.TestCase): + + def setUp(self): + self.session = Session() + self.coleccion = Coleccion() + + def testAgregarCancionSinAlbum(self): + self.coleccion.agregarInterprete("Vicente Fernandez", "Grabado en 3 potrillos", -1) + self.coleccion.agregarInterprete("Alejandro Fernandez", "En honor al aniversario...", -1) + self.coleccion.agregarCancion("Felicidad", 3, 10, "Desconocido", -1, + [{'nombre': 'Vicente Fernandez', 'texto_curiosidades': 'Grabado en 3 potrillos'}, + {'nombre': 'Alejandro Fernandez', + 'texto_curiosidades': 'En honor al aniversario...'}]) + self.consulta1 = self.session.query(Cancion).filter(Cancion.titulo == "Felicidad").first() + self.assertIsNotNone(self.consulta1) + + def testAgregarCancionConAlbum(self): + self.coleccion.agregarAlbum("Renacer", 2005, "Sin descripción", "CD") + self.consulta1 = self.session.query(Album).filter(Album.titulo == "Renacer").first().id + self.coleccion.agregarInterprete("Alejandra Guzman", "Canción dedicada a su ...", -1) + self.coleccion.agregarCancion("Bye mamá", 1, 48, "Desconocido", self.consulta1, + [{'nombre': 'Alejandra Guzman', + 'texto_curiosidades': 'Canción dedicada a su ...'}]) + self.consulta2 = self.session.query(Cancion).filter(Cancion.titulo == "Bye mamá").first() + self.assertIsNotNone(self.consulta2) + + def testEditarCancionSinCambiarInterpretes(self): + self.coleccion.editarCancion(1, "Bye mamá", 2, 54, "J.R.Florez", + [{'id': '2', 'nombre': 'Alejandra Guzman', + 'texto_curiosidades': 'Canción dedicada a su ...'}]) + self.consulta = self.session.query(Cancion).filter(Cancion.id == 1).first() + self.assertEqual(self.consulta.compositor, "J.R.Florez") + + def testEditarCancionInterpretes(self): + self.consulta1 = self.session.query(Cancion).filter(Cancion.id == 1).first().compositor + self.consulta2 = self.session.query(Interprete).filter(Interprete.nombre == "Franco de Vita").first() + if self.consulta2 is None: + self.coleccion.agregarInterprete("Franco de Vita", "Duo con más likes en redes", 1) + self.coleccion.editarCancion(1, "Bye mamá", 4, 23, "J.R.Florez y Difelisatti", + [{'id': '2', 'nombre': 'Alejandra Guzman', + 'texto_curiosidades': 'Canción dedicada a su ...'}, + {'id':'n', 'nombre': 'Franco de Vita', + 'texto_curiosidades': 'Duo con más likes en redes'}]) + else: + self.coleccion.editarCancion(1, "Bye bye", 4, 23, "J.R.Florez y Difelisatti", + [{'id': '2', 'nombre': 'Alejandra Guzman', + 'texto_curiosidades': 'Canción dedicada a su ...'}, + {'id': '9', 'nombre': 'Franco de Vita', + 'texto_curiosidades': 'Duo con más likes en redes'}]) + self.consulta3 = self.session.query(Cancion).filter(Cancion.id == 1).first() + self.assertEqual(self.consulta3.compositor, "J.R.Florez y Difelisatti") + + def testEliminarCancion(self): + self.coleccion.eliminarCancion(2) + self.consulta = self.session.query(Cancion).filter(Cancion.id == 2).first() + self.assertIsNone(self.consulta) + + def testBuscarCancionesPorTitulo(self): + self.coleccion.agregarAlbum("Amapola azul", 2020, "Instrumental", "CD") + self.consulta1 = self.session.query(Album).filter(Album.titulo == "Amapola azul").first().id + self.coleccion.agregarInterprete("Andrea Echeverri", "En ese año nacio su hijo...", -1) + self.coleccion.agregarCancion("Baby blues", 3, 20, "Andrea Echeverri", self.consulta1, + [{'nombre': 'Andrea Echeverri', + 'texto_curiosidades': 'En ese año nacio su hijo...'}]) + self.consulta = self.coleccion.buscarCancionesPorTitulo("Baby") + self.assertGreater(len(self.consulta), 0) + + def testDarCancionPorId(self): + self.consulta = self.coleccion.darCancionPorId(1) + self.assertEqual(self.consulta["titulo"], "Bye mamá") + + def testDarCanciones(self): + self.consulta = self.coleccion.darCanciones() + self.assertNotEqual(self.consulta, []) diff --git a/tests/test_interprete.py b/tests/test_interprete.py new file mode 100644 index 0000000..3405124 --- /dev/null +++ b/tests/test_interprete.py @@ -0,0 +1,54 @@ +import unittest + +from src.logica.Coleccion import Coleccion +from src.modelo.interprete import Interprete +from src.modelo.declarative_base import Session + + +class InterpreteTestCase(unittest.TestCase): + + def setUp(self): + self.session = Session() + self.coleccion = Coleccion() + + def testAgregarInterprete(self): + self.coleccion.agregarInterprete("Adele", "La artista tenia gripa..." , -1) + self.consulta = self.session.query(Interprete).filter(Interprete.nombre == "Adele").first().nombre + self.assertEqual(self.consulta, "Adele") + + def testEditarInterprete(self): + self.coleccion.agregarInterprete("Lady Gaga", "Los trajes usados...", -1) + self.consulta1 = self.session.query(Interprete).filter(Interprete.nombre == "Lady Gaga").first().id + self.consulta2 = self.coleccion.editarInterprete(self.consulta1, "Lady Gaga", "Los trajes usados fueron elaborados...") + self.assertTrue(self.consulta2) + + def testEliminarInterprete(self): + self.coleccion.eliminarInterprete(1) + self.consulta = self.session.query(Interprete).filter(Interprete.id == 1).first() + self.assertIsNone(self.consulta) + + def testBuscarCancionesPorInterprete(self): + self.consulta1 = self.session.query(Interprete).filter(Interprete.nombre == "Pipe Pelaez").first() + if self.consulta1 is None: + self.coleccion.agregarInterprete("Pipe Pelaez", "Primera canción vallenata...", -1) + self.coleccion.agregarCancion("Tan natural", 2, 53, "Manuel Julian", -1, + [{'id':'n', 'nombre': 'Pipe Pelaez', 'texto_curiosidades': 'Primera canción vallenata...'}]) + self.consulta2 = self.coleccion.buscarCancionesPorInterprete("pipe") + self.assertEqual(len(self.consulta2), 1) + + def testBuscarInterpretesPorNombre(self): + self.coleccion.agregarInterprete("Freddie Mercury", "Primera canción como solista", -1) + self.coleccion.agregarInterprete("Freddy Burbano", "Canción que lo catapultó al éxito", -1) + self.consulta = self.coleccion.buscarInterpretesPorNombre("fredd") + self.assertEqual(len(self.consulta), 2) + + def testDarInterpretes(self): + self.coleccion.agregarInterprete("Juan Gabriel", "Al finalizar el concierto en...", -1) + self.consulta = self.coleccion.darInterpretes() + self.assertGreater(len(self.consulta), 0) + + def testDarInterpretePorId(self): + self.coleccion.agregarInterprete("Shakira", "La artista tenía el cabello color rojo", -1) + self.interprete_id = self.session.query(Interprete).filter(Interprete.nombre == "Shakira").first().id + self.consulta = self.coleccion.darInterpretePorId(self.interprete_id)["nombre"] + self.assertEqual(self.consulta, "Shakira")