From 13496f78d3acf2b64a38a5046edafea60e725dd1 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Wed, 1 Apr 2015 17:56:11 +0300 Subject: [PATCH 01/16] Sphinx initial docs --- docs/Makefile | 192 +++++++++++++++++++++++++++++++++ docs/conf.py | 284 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 22 ++++ 3 files changed, 498 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..2914875a --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# 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 coverage gettext + +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 " applehelp to make an Apple Help Book" + @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)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(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: + $(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/objects.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/objects.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/objects" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/objects" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/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: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(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: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(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: + $(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: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(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: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..5f63b156 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# +# objects documentation build configuration file, created by +# sphinx-quickstart on Wed Apr 1 17:36:06 2015. +# +# 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 sys +import os +import shlex + +# 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.abspath('.')) + +# -- 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 = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +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'objects' +copyright = u'2015, Roman Mogilatov' +author = u'Roman Mogilatov' + +# 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 = '0.7.0' +# The full version, including alpha/beta/rc tags. +release = '0.7.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +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 + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = 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 = {} + +# 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". +#html_title = None + +# 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 = None + +# 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'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# 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 + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'objectsdoc' + +# -- 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': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'objects.tex', u'objects Documentation', + u'Roman Mogilatov', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# 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 + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'objects', u'objects Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'objects', u'objects Documentation', + author, 'objects', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..d7fe62c1 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,22 @@ +.. objects documentation master file, created by + sphinx-quickstart on Wed Apr 1 17:36:06 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to objects's documentation! +=================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + From 4ef113f28b6199327f01a86d70819da09a023561 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Thu, 2 Apr 2015 11:57:33 +0300 Subject: [PATCH 02/16] Adding rtd theme, name update --- docs/conf.py | 23 +++++++++++++++++------ docs/index.rst | 8 +++++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5f63b156..8136f35c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# objects documentation build configuration file, created by +# Objects documentation build configuration file, created by # sphinx-quickstart on Wed Apr 1 17:36:06 2015. # # This file is execfile()d with the current directory set to its @@ -46,7 +46,7 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'objects' +project = u'Objects' copyright = u'2015, Roman Mogilatov' author = u'Roman Mogilatov' @@ -202,6 +202,17 @@ html_static_path = ['_static'] # Output file base name for HTML help builder. htmlhelp_basename = 'objectsdoc' +# on_rtd is whether we are on readthedocs.org, this line of code grabbed from +# docs.readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# otherwise, readthedocs.org uses their theme by default, so no need to +# specify it + # -- Options for LaTeX output --------------------------------------------- latex_elements = { @@ -222,7 +233,7 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'objects.tex', u'objects Documentation', + (master_doc, 'Objects.tex', u'Objects Documentation', u'Roman Mogilatov', 'manual'), ] @@ -252,7 +263,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'objects', u'objects Documentation', + (master_doc, 'Objects', u'Objects Documentation', [author], 1) ] @@ -266,8 +277,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'objects', u'objects Documentation', - author, 'objects', 'One line description of project.', + (master_doc, 'Objects', u'Objects Documentation', + author, 'Objects', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/index.rst b/docs/index.rst index d7fe62c1..65520016 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,13 +1,15 @@ -.. objects documentation master file, created by +.. Objects documentation master file, created by sphinx-quickstart on Wed Apr 1 17:36:06 2015. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to objects's documentation! -=================================== +Welcome to Objects documentation! +================================= Contents: +asdadas + .. toctree:: :maxdepth: 2 From 1704c8e05f9bc9309dd42eccaa29f977133e9d26 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Thu, 2 Apr 2015 16:17:00 +0300 Subject: [PATCH 03/16] Adding doc files --- docs/advanced_usage.rst | 201 ++++++++++++++++++++++++++++++++++++++++ docs/entities.rst | 187 +++++++++++++++++++++++++++++++++++++ docs/index.rst | 45 +++++++-- docs/introduction.rst | 16 ++++ 4 files changed, 441 insertions(+), 8 deletions(-) create mode 100644 docs/advanced_usage.rst create mode 100644 docs/entities.rst create mode 100644 docs/introduction.rst diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst new file mode 100644 index 00000000..a0205c6f --- /dev/null +++ b/docs/advanced_usage.rst @@ -0,0 +1,201 @@ +Advanced usage +============== + +Below you can find some variants of advanced usage of `Objects`. + +@inject decorator +----------------- + +`@inject` decorator could be used for patching any callable with injection. +Any Python object will be injected 'as is', except `Objects` providers, +that will be called to provide injectable value. + +.. code-block:: python + + """`@inject` decorator example.""" + + from objects.providers import NewInstance + + from objects.injections import KwArg + from objects.injections import inject + + + new_object = NewInstance(object) + + + @inject(KwArg('object_a', new_object)) + @inject(KwArg('some_setting', 1334)) + def example_callback(object_a, some_setting): + """This function has dependencies on object a and b. + + Dependencies are injected using `@inject` decorator. + """ + assert isinstance(object_a, object) + assert some_setting == 1334 + + + example_callback() + example_callback() + +Overriding providers +-------------------- + +Any provider can be overridden by another provider. + +Example: + +.. code-block:: python + + """Provider overriding example.""" + + import sqlite3 + + from objects.providers import Singleton + from objects.providers import NewInstance + + from objects.injections import KwArg + from objects.injections import Attribute + + + class ObjectA(object): + + """ObjectA has dependency on database.""" + + def __init__(self, database): + """Initializer. + + Database dependency need to be injected via init arg.""" + self.database = database + + def get_one(self): + """Select one from database and return it.""" + return self.database.execute('SELECT 1') + + + class ObjectAMock(ObjectA): + + """Mock of ObjectA. + + Has no dependency on database. + """ + + def __init__(self): + """Initializer.""" + + def get_one(self): + """Select one from database and return it. + + Mock makes no database queries and always returns two instead of one. + """ + return 2 + + + # Database and `ObjectA` providers. + database = Singleton(sqlite3.Connection, + KwArg('database', ':memory:'), + KwArg('timeout', 30), + KwArg('detect_types', True), + KwArg('isolation_level', 'EXCLUSIVE'), + Attribute('row_factory', sqlite3.Row)) + + object_a = NewInstance(ObjectA, + KwArg('database', database)) + + + # Overriding `ObjectA` provider with `ObjectAMock` provider. + object_a.override(NewInstance(ObjectAMock)) + + # Creating several `ObjectA` instances. + object_a_1 = object_a() + object_a_2 = object_a() + + # Making some asserts. + assert object_a_1 is not object_a_2 + assert object_a_1.get_one() == object_a_2.get_one() == 2 + +Overriding catalogs +------------------- + +Any catalog can be overridden by another catalog. + +Example: + +.. code-block:: python + + """Catalog overriding example.""" + + import sqlite3 + + from objects.catalog import AbstractCatalog + from objects.catalog import override + + from objects.providers import Singleton + from objects.providers import NewInstance + + from objects.injections import KwArg + from objects.injections import Attribute + + + class ObjectA(object): + + """ObjectA has dependency on database.""" + + def __init__(self, database): + """Initializer. + + Database dependency need to be injected via init arg.""" + self.database = database + + def get_one(self): + """Select one from database and return it.""" + return self.database.execute('SELECT 1') + + + class ObjectAMock(ObjectA): + + """Mock of ObjectA. + + Has no dependency on database. + """ + + def __init__(self): + """Initializer.""" + + def get_one(self): + """Select one from database and return it. + + Mock makes no database queries and always returns two instead of one. + """ + return 2 + + + class Catalog(AbstractCatalog): + + """Catalog of objects providers.""" + + database = Singleton(sqlite3.Connection, + KwArg('database', ':memory:'), + KwArg('timeout', 30), + KwArg('detect_types', True), + KwArg('isolation_level', 'EXCLUSIVE'), + Attribute('row_factory', sqlite3.Row)) + + object_a = NewInstance(ObjectA, + KwArg('database', database)) + + + @override(Catalog) + class SandboxCatalog(Catalog): + + """Sandbox objects catalog with some mocks that overrides Catalog.""" + + object_a = NewInstance(ObjectAMock) + + + # Creating several `ObjectA` instances. + object_a_1 = Catalog.object_a() + object_a_2 = Catalog.object_a() + + # Making some asserts. + assert object_a_1 is not object_a_2 + assert object_a_1.get_one() == object_a_2.get_one() == 2 diff --git a/docs/entities.rst b/docs/entities.rst new file mode 100644 index 00000000..fb51d247 --- /dev/null +++ b/docs/entities.rst @@ -0,0 +1,187 @@ +Entities +======== + +Current section describes main `Objects` entities and their interaction. + +Providers +--------- + +Providers are strategies of accessing objects. + +All providers are callable. They describe how particular objects will be +provided. For example: + +.. code-block:: python + + """`NewInstance` and `Singleton` providers example.""" + + from objects.providers import NewInstance + from objects.providers import Singleton + + + # NewInstance provider will create new instance of specified class + # on every call. + new_object = NewInstance(object) + + object_1 = new_object() + object_2 = new_object() + + assert object_1 is not object_2 + + # Singleton provider will create new instance of specified class on first call, + # and return same instance on every next call. + single_object = Singleton(object) + + single_object_1 = single_object() + single_object_2 = single_object() + + assert single_object_1 is single_object_2 + +Injections +---------- + +Injections are additional instructions, that are used for determining +dependencies of objects. + +Objects can take dependencies in various forms. Some objects take init +arguments, other are using attributes or methods to be initialized. Injection, +in terms of `Objects`, is an instruction how to provide dependency for the +particular object. + +Every Python object could be an injection's value. Special case is a `Objects` +provider as an injection's value. In such case, injection value is a result of +injectable provider call (every time injection is done). + +Injections are used by providers. + +.. code-block:: python + + """`KwArg` and `Attribute` injections example.""" + + import sqlite3 + + from objects.providers import Singleton + from objects.providers import NewInstance + + from objects.injections import KwArg + from objects.injections import Attribute + + + class ObjectA(object): + + """ObjectA has dependency on database.""" + + def __init__(self, database): + """Initializer. + + Database dependency need to be injected via init arg.""" + self.database = database + + def get_one(self): + """Select one from database and return it.""" + return self.database.execute('SELECT 1').fetchone()[0] + + + # Database and `ObjectA` providers. + database = Singleton(sqlite3.Connection, + KwArg('database', ':memory:'), + KwArg('timeout', 30), + KwArg('detect_types', True), + KwArg('isolation_level', 'EXCLUSIVE'), + Attribute('row_factory', sqlite3.Row)) + + object_a = NewInstance(ObjectA, + KwArg('database', database)) + + # Creating several `ObjectA` instances. + object_a_1 = object_a() + object_a_2 = object_a() + + # Making some asserts. + assert object_a_1 is not object_a_2 + assert object_a_1.database is object_a_2.database + assert object_a_1.get_one() == object_a_2.get_one() == 1 + +Catalogs +-------- + +Catalogs are named set of providers. + +`Objects` catalogs can be used for grouping of providers by some +kind of rules. In example below, there are two catalogs: +`Resources` and `Models`. + +`Resources` catalog is used to group all common application resources like +database connection and various api clients, while `Models` catalog is used +for application model providers only. + +.. code-block:: python + + """Catalogs example.""" + + import sqlite3 + import httplib + + from objects.catalog import AbstractCatalog + + from objects.providers import Singleton + from objects.providers import NewInstance + + from objects.injections import KwArg + from objects.injections import Attribute + + + class SomeModel(object): + + """SomeModel has dependency on database and api client. + + Dependencies need to be injected via init args. + """ + + def __init__(self, database, api_client): + """Initializer.""" + self.database = database + self.api_client = api_client + + def api_request(self): + """Make api request.""" + self.api_client.request('GET', '/') + return self.api_client.getresponse() + + def get_one(self): + """Select one from database and return it.""" + return self.database.execute('SELECT 1').fetchone()[0] + + + class Resources(AbstractCatalog): + + """Resource providers catalog.""" + + database = Singleton(sqlite3.Connection, + KwArg('database', ':memory:'), + KwArg('timeout', 30), + KwArg('detect_types', True), + KwArg('isolation_level', 'EXCLUSIVE'), + Attribute('row_factory', sqlite3.Row)) + + api_client = Singleton(httplib.HTTPConnection, + KwArg('host', 'example.com'), + KwArg('port', 80), + KwArg('timeout', 10)) + + + class Models(AbstractCatalog): + + """Model providers catalog.""" + + some_model = NewInstance(SomeModel, + KwArg('database', Resources.database), + KwArg('api_client', Resources.api_client)) + + + # Creating `SomeModel` instance. + some_model = Models.some_model() + + # Making some asserts. + assert some_model.get_one() == 1 + assert some_model.api_request().status == 200 diff --git a/docs/index.rst b/docs/index.rst index 65520016..aba9a3e4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,17 +3,47 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to Objects documentation! -================================= +Objects +======= -Contents: +Dependency management tool for Python projects. -asdadas - -.. toctree:: - :maxdepth: 2 ++---------------------------------------+-------------------------------------------------------------------+ +| *PyPi* | .. image:: https://pypip.in/version/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Latest Version | +| | .. image:: https://pypip.in/download/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Downloads | +| | .. image:: https://pypip.in/license/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: License | ++---------------------------------------+-------------------------------------------------------------------+ +| *Python versions and implementations* | .. image:: https://pypip.in/py_versions/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Supported Python versions | +| | .. image:: https://pypip.in/implementation/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Supported Python implementations | ++---------------------------------------+-------------------------------------------------------------------+ +| *Builds and test coverage* | .. image:: https://travis-ci.org/rmk135/objects.svg?branch=master | +| | :target: https://travis-ci.org/rmk135/objects | +| | :alt: Build Status | +| | .. image:: https://coveralls.io/repos/rmk135/objects/badge.svg | +| | :target: https://coveralls.io/r/rmk135/objects | +| | :alt: Coverage Status | ++---------------------------------------+-------------------------------------------------------------------+ +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + introduction + entities + advanced_usage Indices and tables ================== @@ -21,4 +51,3 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - diff --git a/docs/introduction.rst b/docs/introduction.rst new file mode 100644 index 00000000..7e5716de --- /dev/null +++ b/docs/introduction.rst @@ -0,0 +1,16 @@ +Introduction +============ + +Python ecosystem consists of a big amount of various classes, functions and +objects that could be used for applications development. Each of them has its +own role. + +Modern Python applications are mostly the composition of well-known open +source systems, frameworks, libraries and some turnkey functionality. + +When application goes bigger, its amount of objects and their dependencies +also increased extremely fast and became hard to maintain. + +`Objects` is designed to be developer's friendly tool for managing objects +and their dependencies in formal, pretty way. Main idea of `Objects` is to +keep dependencies under control. From f2aa8cddc0717d731f3f3f249594b265e4159c93 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Thu, 2 Apr 2015 16:32:10 +0300 Subject: [PATCH 04/16] updating default docs theme --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 8136f35c..75115e63 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -108,7 +108,7 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'alabaster' +html_theme = 'default' # 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 From bab92a58ae0d301aa47548a051a9823863984465 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Thu, 2 Apr 2015 16:44:40 +0300 Subject: [PATCH 05/16] Removing Indicies and Tables from inde --- docs/index.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index aba9a3e4..adba534d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,10 +44,3 @@ Contents introduction entities advanced_usage - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` From bbc5e83e07812e242ab06dbb8008ab17e5fd339c Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Thu, 2 Apr 2015 22:29:49 +0300 Subject: [PATCH 06/16] Adding installation doc --- docs/conf.py | 11 ++++++----- docs/examples.rst | 5 +++++ docs/index.rst | 7 ++----- docs/installation.rst | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 docs/examples.rst create mode 100644 docs/installation.rst diff --git a/docs/conf.py b/docs/conf.py index 75115e63..40823824 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os -import shlex # 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 @@ -55,9 +53,12 @@ author = u'Roman Mogilatov' # built documents. # # The short X.Y version. -version = '0.7.0' +# Getting version. +with open('../VERSION') as version: + version = version.read().strip() + # The full version, including alpha/beta/rc tags. -release = '0.7.0' +release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -278,7 +279,7 @@ man_pages = [ # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'Objects', u'Objects Documentation', - author, 'Objects', 'One line description of project.', + author, 'Objects', 'Dependency management tool for Python projects.', 'Miscellaneous'), ] diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 00000000..d939f79f --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,5 @@ +Examples +======== + +You can get more `Objects` examples in `/examples` directory on +GitHub: https://github.com/rmk135/objects diff --git a/docs/index.rst b/docs/index.rst index adba534d..feba6b4b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,3 @@ -.. Objects documentation master file, created by - sphinx-quickstart on Wed Apr 1 17:36:06 2015. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Objects ======= @@ -42,5 +37,7 @@ Contents :maxdepth: 2 introduction + installation entities advanced_usage + examples diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 00000000..0f9248d4 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,14 @@ +Installation +============ + +Latest stable version of `Objects` library can be installed from PyPi_: + + pip install objects + +Sources can be cloned from GitHub: https://github.com/rmk135/objects + + git clone https://github.com/rmk135/objects.git + +All `Objects` releases can be found on GitHub: https://github.com/rmk135/objects/releases + +.. _PyPi: https://pypi.python.org/pypi/Objects From 1673a110224a66138f94b464fb8f80d992187425 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Thu, 2 Apr 2015 23:46:53 +0300 Subject: [PATCH 07/16] Updating doc styles --- docs/advanced_usage.rst | 6 +++--- docs/entities.rst | 14 +++++++------- docs/examples.rst | 2 +- docs/installation.rst | 7 ++++--- docs/introduction.rst | 4 ++-- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst index a0205c6f..7161bb62 100644 --- a/docs/advanced_usage.rst +++ b/docs/advanced_usage.rst @@ -1,13 +1,13 @@ Advanced usage ============== -Below you can find some variants of advanced usage of `Objects`. +Below you can find some variants of advanced usage of **Objects**. @inject decorator ----------------- -`@inject` decorator could be used for patching any callable with injection. -Any Python object will be injected 'as is', except `Objects` providers, +``@inject`` decorator could be used for patching any callable with injection. +Any Python object will be injected *as is*, except **Objects** providers, that will be called to provide injectable value. .. code-block:: python diff --git a/docs/entities.rst b/docs/entities.rst index fb51d247..7bb31c88 100644 --- a/docs/entities.rst +++ b/docs/entities.rst @@ -1,7 +1,7 @@ Entities ======== -Current section describes main `Objects` entities and their interaction. +Current section describes main **Objects** entities and their interaction. Providers --------- @@ -45,10 +45,10 @@ dependencies of objects. Objects can take dependencies in various forms. Some objects take init arguments, other are using attributes or methods to be initialized. Injection, -in terms of `Objects`, is an instruction how to provide dependency for the +in terms of **Objects**, is an instruction how to provide dependency for the particular object. -Every Python object could be an injection's value. Special case is a `Objects` +Every Python object could be an injection's value. Special case is a **Objects** provider as an injection's value. In such case, injection value is a result of injectable provider call (every time injection is done). @@ -107,12 +107,12 @@ Catalogs Catalogs are named set of providers. -`Objects` catalogs can be used for grouping of providers by some +**Objects** catalogs can be used for grouping of providers by some kind of rules. In example below, there are two catalogs: -`Resources` and `Models`. +``Resources`` and ``Models``. -`Resources` catalog is used to group all common application resources like -database connection and various api clients, while `Models` catalog is used +``Resources`` catalog is used to group all common application resources like +database connection and various api clients, while ``Models`` catalog is used for application model providers only. .. code-block:: python diff --git a/docs/examples.rst b/docs/examples.rst index d939f79f..890e527d 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -1,5 +1,5 @@ Examples ======== -You can get more `Objects` examples in `/examples` directory on +You can get more **Objects** examples in ``/examples`` directory on GitHub: https://github.com/rmk135/objects diff --git a/docs/installation.rst b/docs/installation.rst index 0f9248d4..046009bf 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -1,14 +1,15 @@ Installation ============ -Latest stable version of `Objects` library can be installed from PyPi_: +Latest stable version of **Objects** library can be installed from PyPi_:: pip install objects -Sources can be cloned from GitHub: https://github.com/rmk135/objects +Sources can be cloned from GitHub_:: git clone https://github.com/rmk135/objects.git -All `Objects` releases can be found on GitHub: https://github.com/rmk135/objects/releases +All **Objects** releases can be found on GitHub: https://github.com/rmk135/objects/releases .. _PyPi: https://pypi.python.org/pypi/Objects +.. _GitHub: https://github.com/rmk135/objects diff --git a/docs/introduction.rst b/docs/introduction.rst index 7e5716de..a60cd478 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -11,6 +11,6 @@ source systems, frameworks, libraries and some turnkey functionality. When application goes bigger, its amount of objects and their dependencies also increased extremely fast and became hard to maintain. -`Objects` is designed to be developer's friendly tool for managing objects -and their dependencies in formal, pretty way. Main idea of `Objects` is to +**Objects** is designed to be developer's friendly tool for managing objects +and their dependencies in formal, pretty way. Main idea of **Objects** is to keep dependencies under control. From 74bb47626dd346d056b468b4d341df8cc54432d7 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:04:36 +0300 Subject: [PATCH 08/16] Adding feedback page --- docs/feedback.rst | 10 ++++++++++ docs/index.rst | 1 + 2 files changed, 11 insertions(+) create mode 100644 docs/feedback.rst diff --git a/docs/feedback.rst b/docs/feedback.rst new file mode 100644 index 00000000..d2f22925 --- /dev/null +++ b/docs/feedback.rst @@ -0,0 +1,10 @@ +Feedback +======== + + +Feel free to post questions, bugs, feature requests, proposals etc. on +**Objects** GitHub Issues: + + https://github.com/rmk135/objects/issues + +Your feedback is quite important! diff --git a/docs/index.rst b/docs/index.rst index feba6b4b..f472cb2f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -41,3 +41,4 @@ Contents entities advanced_usage examples + feedback From 48fce40e5a729fad527a678546243a5675bf29f0 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 3 Apr 2015 00:11:19 +0300 Subject: [PATCH 09/16] Update README.md --- README.md | 384 ++---------------------------------------------------- 1 file changed, 8 insertions(+), 376 deletions(-) diff --git a/README.md b/README.md index 8723c207..93c63949 100644 --- a/README.md +++ b/README.md @@ -26,385 +26,17 @@ also increased extremely fast and became hard to maintain. and their dependencies in formal, pretty way. Main idea of `Objects` is to keep dependencies under control. -## Entities +## Installation -Current section describes main `Objects` entities and their interaction. +Objects library is available on [PyPi](https://pypi.python.org/pypi/Objects): -### Providers - -Providers are strategies of accessing objects. - -All providers are callable. They describe how particular objects will be -provided. For example: - -```python -"""`NewInstance` and `Singleton` providers example.""" - -from objects.providers import NewInstance -from objects.providers import Singleton - - -# NewInstance provider will create new instance of specified class -# on every call. -new_object = NewInstance(object) - -object_1 = new_object() -object_2 = new_object() - -assert object_1 is not object_2 - -# Singleton provider will create new instance of specified class on first call, -# and return same instance on every next call. -single_object = Singleton(object) - -single_object_1 = single_object() -single_object_2 = single_object() - -assert single_object_1 is single_object_2 +``` +pip install objects ``` -### Injections +## Documentation -Injections are additional instructions, that are used for determining -dependencies of objects. +`Objects` documentation is hosted on ReadTheDocs: -Objects can take dependencies in various forms. Some objects take init -arguments, other are using attributes or methods to be initialized. Injection, -in terms of `Objects`, is an instruction how to provide dependency for the -particular object. - -Every Python object could be an injection's value. Special case is a `Objects` -provider as an injection's value. In such case, injection value is a result of -injectable provider call (every time injection is done). - -Injections are used by providers. - -```python -"""`KwArg` and `Attribute` injections example.""" - -import sqlite3 - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class ObjectA(object): - - """ObjectA has dependency on database.""" - - def __init__(self, database): - """Initializer. - - Database dependency need to be injected via init arg.""" - self.database = database - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1').fetchone()[0] - - -# Database and `ObjectA` providers. -database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - -object_a = NewInstance(ObjectA, - KwArg('database', database)) - -# Creating several `ObjectA` instances. -object_a_1 = object_a() -object_a_2 = object_a() - -# Making some asserts. -assert object_a_1 is not object_a_2 -assert object_a_1.database is object_a_2.database -assert object_a_1.get_one() == object_a_2.get_one() == 1 -``` - -### Catalogs - -Catalogs are named set of providers. - -`Objects` catalogs can be used for grouping of providers by some -kind of rules. In example below, there are two catalogs: -`Resources` and `Models`. - -`Resources` catalog is used to group all common application resources like -database connection and various api clients, while `Models` catalog is used -for application model providers only. - -```python -"""Catalogs example.""" - -import sqlite3 -import httplib - -from objects.catalog import AbstractCatalog - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class SomeModel(object): - - """SomeModel has dependency on database and api client. - - Dependencies need to be injected via init args. - """ - - def __init__(self, database, api_client): - """Initializer.""" - self.database = database - self.api_client = api_client - - def api_request(self): - """Make api request.""" - self.api_client.request('GET', '/') - return self.api_client.getresponse() - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1').fetchone()[0] - - -class Resources(AbstractCatalog): - - """Resource providers catalog.""" - - database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - - api_client = Singleton(httplib.HTTPConnection, - KwArg('host', 'example.com'), - KwArg('port', 80), - KwArg('timeout', 10)) - - -class Models(AbstractCatalog): - - """Model providers catalog.""" - - some_model = NewInstance(SomeModel, - KwArg('database', Resources.database), - KwArg('api_client', Resources.api_client)) - - -# Creating `SomeModel` instance. -some_model = Models.some_model() - -# Making some asserts. -assert some_model.get_one() == 1 -assert some_model.api_request().status == 200 -``` - -## Advanced usage - -Below you can find some variants of advanced usage of `Objects`. - -### Inject decorator - -`@inject` decorator could be used for patching any callable with injection. -Any Python object will be injected 'as is', except `Objects` providers, -that will be called to provide injectable value. - - -```python -"""`@inject` decorator example.""" - -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import inject - - -new_object = NewInstance(object) - - -@inject(KwArg('object_a', new_object)) -@inject(KwArg('some_setting', 1334)) -def example_callback(object_a, some_setting): - """This function has dependencies on object a and b. - - Dependencies are injected using `@inject` decorator. - """ - assert isinstance(object_a, object) - assert some_setting == 1334 - - -example_callback() -example_callback() -``` - -### Overriding providers - -Any provider can be overridden by another provider. - -Example: - -```python -"""Provider overriding example.""" - -import sqlite3 - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class ObjectA(object): - - """ObjectA has dependency on database.""" - - def __init__(self, database): - """Initializer. - - Database dependency need to be injected via init arg.""" - self.database = database - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1') - - -class ObjectAMock(ObjectA): - - """Mock of ObjectA. - - Has no dependency on database. - """ - - def __init__(self): - """Initializer.""" - - def get_one(self): - """Select one from database and return it. - - Mock makes no database queries and always returns two instead of one. - """ - return 2 - - -# Database and `ObjectA` providers. -database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - -object_a = NewInstance(ObjectA, - KwArg('database', database)) - - -# Overriding `ObjectA` provider with `ObjectAMock` provider. -object_a.override(NewInstance(ObjectAMock)) - -# Creating several `ObjectA` instances. -object_a_1 = object_a() -object_a_2 = object_a() - -# Making some asserts. -assert object_a_1 is not object_a_2 -assert object_a_1.get_one() == object_a_2.get_one() == 2 -``` - -### Overriding catalogs - -Any catalog can be overridden by another catalog. - -Example: - -```python -"""Catalog overriding example.""" - -import sqlite3 - -from objects.catalog import AbstractCatalog -from objects.catalog import override - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class ObjectA(object): - - """ObjectA has dependency on database.""" - - def __init__(self, database): - """Initializer. - - Database dependency need to be injected via init arg.""" - self.database = database - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1') - - -class ObjectAMock(ObjectA): - - """Mock of ObjectA. - - Has no dependency on database. - """ - - def __init__(self): - """Initializer.""" - - def get_one(self): - """Select one from database and return it. - - Mock makes no database queries and always returns two instead of one. - """ - return 2 - - -class Catalog(AbstractCatalog): - - """Catalog of objects providers.""" - - database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - - object_a = NewInstance(ObjectA, - KwArg('database', database)) - - -@override(Catalog) -class SandboxCatalog(Catalog): - - """Sandbox objects catalog with some mocks that overrides Catalog.""" - - object_a = NewInstance(ObjectAMock) - - -# Creating several `ObjectA` instances. -object_a_1 = Catalog.object_a() -object_a_2 = Catalog.object_a() - -# Making some asserts. -assert object_a_1 is not object_a_2 -assert object_a_1.get_one() == object_a_2.get_one() == 2 -``` +- [Stable version](http://objects.readthedocs.org/en/stable/) +- [Latest version](http://objects.readthedocs.org/en/latest/) From 2880eaa72710060df5e4c81bad836f8f33fd3e9f Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:29:00 +0300 Subject: [PATCH 10/16] Adding readme in rst format --- README.rst | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 README.rst diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..0db52d3d --- /dev/null +++ b/README.rst @@ -0,0 +1,67 @@ +Objects +======= + +Dependency management tool for Python projects. + ++---------------------------------------+-------------------------------------------------------------------+ +| *PyPi* | .. image:: https://pypip.in/version/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Latest Version | +| | .. image:: https://pypip.in/download/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Downloads | +| | .. image:: https://pypip.in/license/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: License | ++---------------------------------------+-------------------------------------------------------------------+ +| *Python versions and implementations* | .. image:: https://pypip.in/py_versions/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Supported Python versions | +| | .. image:: https://pypip.in/implementation/Objects/badge.svg | +| | :target: https://pypi.python.org/pypi/Objects/ | +| | :alt: Supported Python implementations | ++---------------------------------------+-------------------------------------------------------------------+ +| *Builds and test coverage* | .. image:: https://travis-ci.org/rmk135/objects.svg?branch=master | +| | :target: https://travis-ci.org/rmk135/objects | +| | :alt: Build Status | +| | .. image:: https://coveralls.io/repos/rmk135/objects/badge.svg | +| | :target: https://coveralls.io/r/rmk135/objects | +| | :alt: Coverage Status | ++---------------------------------------+-------------------------------------------------------------------+ + +Introduction +------------ + +Python ecosystem consists of a big amount of various classes, functions and +objects that could be used for applications development. Each of them has its +own role. + +Modern Python applications are mostly the composition of well-known open +source systems, frameworks, libraries and some turnkey functionality. + +When application goes bigger, its amount of objects and their dependencies +also increased extremely fast and became hard to maintain. + +**Objects** is designed to be developer's friendly tool for managing objects +and their dependencies in formal, pretty way. Main idea of **Objects** is to +keep dependencies under control. + +Installation +------------ + +**Objects** library is available on PyPi_:: + + pip install objects + +Documentation +------------- + +**Objects** documentation is hosted on ReadTheDocs: + +- `Stable version`_ +- `Latest version`_ + + +.. _PyPi: https://pypi.python.org/pypi/Objects +.. _Stable version: http://objects.readthedocs.org/en/stable/ +.. _Latest version: http://objects.readthedocs.org/en/latest/ From 460038f3afcce2eff2235e7d45155c4bdb9c0c12 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:31:26 +0300 Subject: [PATCH 11/16] Removing README.md --- MANIFEST.in | 2 +- README.md | 410 ---------------------------------------------------- setup.py | 9 +- 3 files changed, 3 insertions(+), 418 deletions(-) delete mode 100644 README.md diff --git a/MANIFEST.in b/MANIFEST.in index 1fa3050c..14229e80 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ include objects/* -include README.md +include README.rst include LICENSE include VERSION include requirements.txt diff --git a/README.md b/README.md deleted file mode 100644 index 8723c207..00000000 --- a/README.md +++ /dev/null @@ -1,410 +0,0 @@ -# Objects - -Dependency management tool for Python projects. - -[![Latest Version](https://pypip.in/version/Objects/badge.svg)](https://pypi.python.org/pypi/Objects/) -[![Downloads](https://pypip.in/download/Objects/badge.svg)](https://pypi.python.org/pypi/Objects/) -[![Build Status](https://travis-ci.org/rmk135/objects.svg?branch=master)](https://travis-ci.org/rmk135/objects) -[![Coverage Status](https://coveralls.io/repos/rmk135/objects/badge.svg)](https://coveralls.io/r/rmk135/objects) -[![License](https://pypip.in/license/Objects/badge.svg)](https://pypi.python.org/pypi/Objects/) -[![Supported Python versions](https://pypip.in/py_versions/Objects/badge.svg)](https://pypi.python.org/pypi/Objects/) -[![Supported Python implementations](https://pypip.in/implementation/Objects/badge.svg)](https://pypi.python.org/pypi/Objects/) - -## Introduction - -Python ecosystem consists of a big amount of various classes, functions and -objects that could be used for applications development. Each of them has its -own role. - -Modern Python applications are mostly the composition of well-known open -source systems, frameworks, libraries and some turnkey functionality. - -When application goes bigger, its amount of objects and their dependencies -also increased extremely fast and became hard to maintain. - -`Objects` is designed to be developer's friendly tool for managing objects -and their dependencies in formal, pretty way. Main idea of `Objects` is to -keep dependencies under control. - -## Entities - -Current section describes main `Objects` entities and their interaction. - -### Providers - -Providers are strategies of accessing objects. - -All providers are callable. They describe how particular objects will be -provided. For example: - -```python -"""`NewInstance` and `Singleton` providers example.""" - -from objects.providers import NewInstance -from objects.providers import Singleton - - -# NewInstance provider will create new instance of specified class -# on every call. -new_object = NewInstance(object) - -object_1 = new_object() -object_2 = new_object() - -assert object_1 is not object_2 - -# Singleton provider will create new instance of specified class on first call, -# and return same instance on every next call. -single_object = Singleton(object) - -single_object_1 = single_object() -single_object_2 = single_object() - -assert single_object_1 is single_object_2 -``` - -### Injections - -Injections are additional instructions, that are used for determining -dependencies of objects. - -Objects can take dependencies in various forms. Some objects take init -arguments, other are using attributes or methods to be initialized. Injection, -in terms of `Objects`, is an instruction how to provide dependency for the -particular object. - -Every Python object could be an injection's value. Special case is a `Objects` -provider as an injection's value. In such case, injection value is a result of -injectable provider call (every time injection is done). - -Injections are used by providers. - -```python -"""`KwArg` and `Attribute` injections example.""" - -import sqlite3 - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class ObjectA(object): - - """ObjectA has dependency on database.""" - - def __init__(self, database): - """Initializer. - - Database dependency need to be injected via init arg.""" - self.database = database - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1').fetchone()[0] - - -# Database and `ObjectA` providers. -database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - -object_a = NewInstance(ObjectA, - KwArg('database', database)) - -# Creating several `ObjectA` instances. -object_a_1 = object_a() -object_a_2 = object_a() - -# Making some asserts. -assert object_a_1 is not object_a_2 -assert object_a_1.database is object_a_2.database -assert object_a_1.get_one() == object_a_2.get_one() == 1 -``` - -### Catalogs - -Catalogs are named set of providers. - -`Objects` catalogs can be used for grouping of providers by some -kind of rules. In example below, there are two catalogs: -`Resources` and `Models`. - -`Resources` catalog is used to group all common application resources like -database connection and various api clients, while `Models` catalog is used -for application model providers only. - -```python -"""Catalogs example.""" - -import sqlite3 -import httplib - -from objects.catalog import AbstractCatalog - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class SomeModel(object): - - """SomeModel has dependency on database and api client. - - Dependencies need to be injected via init args. - """ - - def __init__(self, database, api_client): - """Initializer.""" - self.database = database - self.api_client = api_client - - def api_request(self): - """Make api request.""" - self.api_client.request('GET', '/') - return self.api_client.getresponse() - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1').fetchone()[0] - - -class Resources(AbstractCatalog): - - """Resource providers catalog.""" - - database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - - api_client = Singleton(httplib.HTTPConnection, - KwArg('host', 'example.com'), - KwArg('port', 80), - KwArg('timeout', 10)) - - -class Models(AbstractCatalog): - - """Model providers catalog.""" - - some_model = NewInstance(SomeModel, - KwArg('database', Resources.database), - KwArg('api_client', Resources.api_client)) - - -# Creating `SomeModel` instance. -some_model = Models.some_model() - -# Making some asserts. -assert some_model.get_one() == 1 -assert some_model.api_request().status == 200 -``` - -## Advanced usage - -Below you can find some variants of advanced usage of `Objects`. - -### Inject decorator - -`@inject` decorator could be used for patching any callable with injection. -Any Python object will be injected 'as is', except `Objects` providers, -that will be called to provide injectable value. - - -```python -"""`@inject` decorator example.""" - -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import inject - - -new_object = NewInstance(object) - - -@inject(KwArg('object_a', new_object)) -@inject(KwArg('some_setting', 1334)) -def example_callback(object_a, some_setting): - """This function has dependencies on object a and b. - - Dependencies are injected using `@inject` decorator. - """ - assert isinstance(object_a, object) - assert some_setting == 1334 - - -example_callback() -example_callback() -``` - -### Overriding providers - -Any provider can be overridden by another provider. - -Example: - -```python -"""Provider overriding example.""" - -import sqlite3 - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class ObjectA(object): - - """ObjectA has dependency on database.""" - - def __init__(self, database): - """Initializer. - - Database dependency need to be injected via init arg.""" - self.database = database - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1') - - -class ObjectAMock(ObjectA): - - """Mock of ObjectA. - - Has no dependency on database. - """ - - def __init__(self): - """Initializer.""" - - def get_one(self): - """Select one from database and return it. - - Mock makes no database queries and always returns two instead of one. - """ - return 2 - - -# Database and `ObjectA` providers. -database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - -object_a = NewInstance(ObjectA, - KwArg('database', database)) - - -# Overriding `ObjectA` provider with `ObjectAMock` provider. -object_a.override(NewInstance(ObjectAMock)) - -# Creating several `ObjectA` instances. -object_a_1 = object_a() -object_a_2 = object_a() - -# Making some asserts. -assert object_a_1 is not object_a_2 -assert object_a_1.get_one() == object_a_2.get_one() == 2 -``` - -### Overriding catalogs - -Any catalog can be overridden by another catalog. - -Example: - -```python -"""Catalog overriding example.""" - -import sqlite3 - -from objects.catalog import AbstractCatalog -from objects.catalog import override - -from objects.providers import Singleton -from objects.providers import NewInstance - -from objects.injections import KwArg -from objects.injections import Attribute - - -class ObjectA(object): - - """ObjectA has dependency on database.""" - - def __init__(self, database): - """Initializer. - - Database dependency need to be injected via init arg.""" - self.database = database - - def get_one(self): - """Select one from database and return it.""" - return self.database.execute('SELECT 1') - - -class ObjectAMock(ObjectA): - - """Mock of ObjectA. - - Has no dependency on database. - """ - - def __init__(self): - """Initializer.""" - - def get_one(self): - """Select one from database and return it. - - Mock makes no database queries and always returns two instead of one. - """ - return 2 - - -class Catalog(AbstractCatalog): - - """Catalog of objects providers.""" - - database = Singleton(sqlite3.Connection, - KwArg('database', ':memory:'), - KwArg('timeout', 30), - KwArg('detect_types', True), - KwArg('isolation_level', 'EXCLUSIVE'), - Attribute('row_factory', sqlite3.Row)) - - object_a = NewInstance(ObjectA, - KwArg('database', database)) - - -@override(Catalog) -class SandboxCatalog(Catalog): - - """Sandbox objects catalog with some mocks that overrides Catalog.""" - - object_a = NewInstance(ObjectAMock) - - -# Creating several `ObjectA` instances. -object_a_1 = Catalog.object_a() -object_a_2 = Catalog.object_a() - -# Making some asserts. -assert object_a_1 is not object_a_2 -assert object_a_1.get_one() == object_a_2.get_one() == 2 -``` diff --git a/setup.py b/setup.py index 0946aa08..4a9f9142 100644 --- a/setup.py +++ b/setup.py @@ -6,13 +6,8 @@ from setuptools import setup # Getting description. -try: - import pypandoc -except (IOError, ImportError): - with open('README.md') as readme_file: - description = readme_file.read() -else: - description = pypandoc.convert('README.md', 'rst', format='markdown') +with open('README.rst') as readme_file: + description = readme_file.read() # Getting requirements. From a0e0d4dc3f87ef2ab6aa4cd6526be3d6423f2dbe Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:33:28 +0300 Subject: [PATCH 12/16] Adding feedback section to README --- README.rst | 10 ++++++++++ docs/feedback.rst | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 0db52d3d..437a4e11 100644 --- a/README.rst +++ b/README.rst @@ -61,6 +61,16 @@ Documentation - `Stable version`_ - `Latest version`_ +Feedback +======== + +Feel free to post questions, bugs, feature requests, proposals etc. on +**Objects** GitHub Issues: + + https://github.com/rmk135/objects/issues + +Your feedback is quite important! + .. _PyPi: https://pypi.python.org/pypi/Objects .. _Stable version: http://objects.readthedocs.org/en/stable/ diff --git a/docs/feedback.rst b/docs/feedback.rst index d2f22925..df25c405 100644 --- a/docs/feedback.rst +++ b/docs/feedback.rst @@ -1,7 +1,6 @@ Feedback ======== - Feel free to post questions, bugs, feature requests, proposals etc. on **Objects** GitHub Issues: From 25f1c222fd263d0eb3b9e69d1f222ee10f15f86f Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:35:22 +0300 Subject: [PATCH 13/16] Adding examples seactions to readme --- README.rst | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 437a4e11..d1956cbc 100644 --- a/README.rst +++ b/README.rst @@ -61,8 +61,88 @@ Documentation - `Stable version`_ - `Latest version`_ +Examples +-------- + +.. code-block:: python + + """Concept example of `Objects`.""" + + from objects.catalog import AbstractCatalog + + from objects.providers import Singleton + from objects.providers import NewInstance + + from objects.injections import KwArg + from objects.injections import Attribute + from objects.injections import inject + + import sqlite3 + + + class ObjectA(object): + + """Example class ObjectA, that has dependency on database.""" + + def __init__(self, db): + """Initializer.""" + self.db = db + + + class ObjectB(object): + + """Example class ObjectB, that has dependencies on ObjectA and database.""" + + def __init__(self, a, db): + """Initializer.""" + self.a = a + self.db = db + + + class Catalog(AbstractCatalog): + + """Catalog of objects providers.""" + + database = Singleton(sqlite3.Connection, + KwArg('database', ':memory:'), + Attribute('row_factory', sqlite3.Row)) + """:type: (objects.Provider) -> sqlite3.Connection""" + + object_a = NewInstance(ObjectA, + KwArg('db', database)) + """:type: (objects.Provider) -> ObjectA""" + + object_b = NewInstance(ObjectB, + KwArg('a', object_a), + KwArg('db', database)) + """:type: (objects.Provider) -> ObjectB""" + + + # Catalog static provides. + a1, a2 = Catalog.object_a(), Catalog.object_a() + b1, b2 = Catalog.object_b(), Catalog.object_b() + + assert a1 is not a2 + assert b1 is not b2 + assert a1.db is a2.db is b1.db is b2.db is Catalog.database() + + + # Example of inline injections. + @inject(KwArg('a', Catalog.object_a)) + @inject(KwArg('b', Catalog.object_b)) + @inject(KwArg('database', Catalog.database)) + def example(a, b, database): + assert a.db is b.db is database is Catalog.database() + + + example() + +You can get more **Objects** examples in ``/examples`` directory on +GitHub: https://github.com/rmk135/objects + + Feedback -======== +-------- Feel free to post questions, bugs, feature requests, proposals etc. on **Objects** GitHub Issues: From fb581ce47d425e7538258ec473b198c43b25869a Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:37:08 +0300 Subject: [PATCH 14/16] Removing GitHub from README --- README.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index d1956cbc..0f226ae0 100644 --- a/README.rst +++ b/README.rst @@ -137,15 +137,14 @@ Examples example() -You can get more **Objects** examples in ``/examples`` directory on -GitHub: https://github.com/rmk135/objects +You can get more **Objects** examples in ``/examples`` directory. Feedback -------- Feel free to post questions, bugs, feature requests, proposals etc. on -**Objects** GitHub Issues: +**Objects** Issues: https://github.com/rmk135/objects/issues From 22de89c206b199d392565e2e023f03625dc396ae Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:37:49 +0300 Subject: [PATCH 15/16] Updating readme --- README.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 0f226ae0..d1956cbc 100644 --- a/README.rst +++ b/README.rst @@ -137,14 +137,15 @@ Examples example() -You can get more **Objects** examples in ``/examples`` directory. +You can get more **Objects** examples in ``/examples`` directory on +GitHub: https://github.com/rmk135/objects Feedback -------- Feel free to post questions, bugs, feature requests, proposals etc. on -**Objects** Issues: +**Objects** GitHub Issues: https://github.com/rmk135/objects/issues From 78dd20ef39e07320c02f3093e1d2961730b46c19 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Fri, 3 Apr 2015 00:40:03 +0300 Subject: [PATCH 16/16] Updating examples section --- README.rst | 4 +++- docs/examples.rst | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index d1956cbc..da72acdc 100644 --- a/README.rst +++ b/README.rst @@ -138,7 +138,9 @@ Examples example() You can get more **Objects** examples in ``/examples`` directory on -GitHub: https://github.com/rmk135/objects +GitHub: + + https://github.com/rmk135/objects Feedback diff --git a/docs/examples.rst b/docs/examples.rst index 890e527d..5b2b4fa2 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -2,4 +2,7 @@ Examples ======== You can get more **Objects** examples in ``/examples`` directory on -GitHub: https://github.com/rmk135/objects +GitHub: + + https://github.com/rmk135/objects +