├── .gitignore ├── Makefile ├── README.md ├── cant ├── __init__.py ├── alpha_status.py ├── arity.py ├── comparison_functions.py ├── get_callables.py ├── rem.py └── tests │ ├── __init__.py │ └── run_tests.py ├── conf.py ├── deploy.py ├── index.rst ├── setup.cfg ├── setup.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *#* 3 | *.DS_STORE 4 | *.log 5 | *Data.fs* 6 | *flymake* 7 | *egg* 8 | build/ 9 | __pycache__/ 10 | /.Python 11 | /bin/ 12 | /include/ 13 | /lib/ 14 | /pip-selfcheck.json 15 | .tox/ 16 | comments/ 17 | dist/ 18 | *silly* 19 | extras/ 20 | .cache/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(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/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/cant.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/cant.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/cant" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/cant" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## cant 2 | 3 | The main idea was that sometimes I know it is possible to get some output given some input but I forgot the name of the function I'm looking for. This module can find that function for you. Some kind of reverse engineering if you will. 4 | 5 | Specify the `input` and `expected` value. Optionally you can give it arguments. 6 | 7 | It then uses: 8 | 9 | - `globals` 10 | - functions from a module 11 | - `builtins` 12 | - the object's methods, and 13 | - class methods 14 | 15 | in an attempt to find functions that that can bring `inp` to `expected`. 16 | 17 | E.g.: 18 | 19 | # The following will give '__mul__' as an option 20 | remember(inp=5, expected=15, args=3) 21 | 22 | # since 23 | 5.__mul__(3) == 15 24 | 25 | Obviously you don't need help with this particular case. But it gets interesting when you throw in your own classes into the mix, or you just know e.g. the module, but not the function that can get the required output; has happened to me with `itertools` (hint: look in [run_tests.py](https://github.com/kootenpv/cant/blob/master/cant/tests/run_tests.py#L107) examples). 26 | 27 | This was a great practice for working with all kinds of arities (0, 1, starred, 1+starred, 2) and scopes (global, modules, objects, builtins). 28 | 29 | **Warning**: it makes copies of all simple objects to enable using functions that modify the object in place and while not affecting the "outside" scope. However, database stuff etc that would not be able to be rolled back by `copy` should be considered unsafe. 30 | 31 | ### Usage 32 | 33 | Use the `cant.remember` function to find all functions that bring `inp` (and optionally, `args`) to `expected`, e.g.: 34 | 35 | ```python 36 | [In] cant.remember(inp=5, expected=15, args=3) 37 | 38 | [Out] [{'arity': '1', 'callable': '__mul__', 'input': 5, 'namespace': 'self'}, 39 | {'arity': '1', 'callable': '__rmul__', 'input': 5, 'namespace': 'self'}] 40 | ``` 41 | 42 | Use the `cant.depth_two` (alpha-status; should be generalized to `depth_n`) function to find all functions that go depth two, e.g.: 43 | 44 | ```python 45 | [In] cant.depth_two(inp=[5], expected=15, args=3) 46 | 47 | [Out] ['[5].pop() = 5 ---> 5.__mul__(3) = 15', 48 | '[5].pop() = 5 ---> 5.__rmul__(3) = 15'] 49 | ``` 50 | What happens there is that it considers all possibilities, and the first that works is: 51 | 52 | - use the attribute `pop` of the list input object `[5]` 53 | - take the value of `[5].pop()` which is `5` 54 | - out of all the options for the object `5`, use `__mul__` 55 | - `inp.pop().__mul__(args) == expected` was found to hold (`5*3==15`) 56 | 57 | Actually, in the example above it tried all possible combinations at both levels and found `pop`ping and using `__mul__` to be satisfying the `input -> ... -> expected` condition. 58 | 59 | See `tests/run_tests.py` for more/documented examples. 60 | 61 | ### Installation 62 | 63 | `tox` tests for Python 2.7, Python 3.4 and Python 3.5: all tests pass. 64 | 65 | It's on pip: 66 | 67 | pip install cant 68 | -------------------------------------------------------------------------------- /cant/__init__.py: -------------------------------------------------------------------------------- 1 | """ remember - Catchy catchphrase """ 2 | 3 | __project__ = 'cant' 4 | __version__ = '0.0.0' 5 | 6 | from cant.alpha_status import depth_two 7 | from cant.rem import remember 8 | 9 | 10 | __all__ = ['remember', 'depth_two'] 11 | -------------------------------------------------------------------------------- /cant/alpha_status.py: -------------------------------------------------------------------------------- 1 | """Working on chaining results from remember. """ 2 | 3 | import copy 4 | 5 | from cant.arity import PassAnything 6 | from cant.rem import remember 7 | 8 | 9 | class NoValidResultError(Exception): 10 | pass 11 | 12 | 13 | def call_self_by_arity(fn, x, arity): 14 | if isinstance(fn, str): 15 | fn = getattr(x, fn) 16 | try: 17 | if arity == '1': 18 | return fn(x) 19 | else: 20 | return fn() 21 | except: 22 | raise NoValidResultError 23 | 24 | 25 | def depth_two(inp, expected, args): 26 | results = [] 27 | depth_2_template = '{}.{}({}) = {} ---> {}.{}({}) = {}' 28 | for x in remember(inp, PassAnything(), args): 29 | newinp = copy.copy(inp) 30 | try: 31 | res = call_self_by_arity(x['callable'], newinp, x['arity']) 32 | arg1 = args if x['arity'] == '1' else '' 33 | except NoValidResultError: 34 | continue 35 | try: 36 | n = remember(res, expected, args) 37 | # catching Python 2.x: 38 | # TypeError: object.__new__(listiterator) is not safe, use listiterator.__new__() 39 | except TypeError: 40 | continue 41 | oldinp = copy.copy(newinp) 42 | for r in n: 43 | if r['arity'] == '1': 44 | arg2 = args 45 | elif r['arity'] == 'starred': 46 | arg2 = '*' + str(args) 47 | else: 48 | arg2 = '' 49 | results.append( 50 | depth_2_template.format( 51 | inp, x['callable'], arg1, res, res, r['callable'], arg2, expected 52 | ) 53 | ) 54 | return results 55 | -------------------------------------------------------------------------------- /cant/arity.py: -------------------------------------------------------------------------------- 1 | """ This module contains the versions that test whether func(inp) == expected. 2 | In order to use a function, it has to be checked for multiple number of arguments. 3 | Either zero, one, one + starred, or two. """ 4 | 5 | 6 | # ADD ALSO ATTRIBUTE TESTS, e.g. yag.owner.login == 'kootenpv' when i was looking for owner 7 | 8 | # TODO: I'm starting to think that I'm still missing a case with star args: 9 | # - fn(*args), args 10 | # - fn(*args), *args 11 | # - fn(args), args 12 | # - fn(args), *args 13 | import copy 14 | 15 | 16 | # I'm literally trying to catch ANY exception in arity.py. 17 | # pylint: disable=bare-except 18 | 19 | 20 | class PassAnything(object): 21 | """ When a PassAnything object is given to be evaluated, it will pass if there is no error. """ 22 | # pylint: disable=too-few-public-methods 23 | pass 24 | 25 | 26 | def get_copied_input_and_callable(inp, callab): 27 | """ collab remains either str or callable, while clb is callable 28 | in case of 'str', it's a sign also of "self" and it has to be getattr'ed 29 | I do this because class instance methods are now possible as well """ 30 | safe_inp = copy.copy(inp) 31 | clb = getattr(safe_inp, callab) if isinstance(callab, str) else callab 32 | return safe_inp, clb 33 | 34 | 35 | def arity_zero(callab, inp, expected, equality_fun, namespace): 36 | """ Only going to pass for functions that take NO arguments. """ 37 | res = {} 38 | try: 39 | _, clb = get_copied_input_and_callable(inp, callab) 40 | if equality_fun(clb(), expected) or isinstance(expected, PassAnything): 41 | res = {'arity': '0', 'namespace': namespace, 'callable': callab} 42 | except: 43 | pass 44 | return res 45 | 46 | 47 | def arity_one_self(callab, inp, expected, equality_fun, namespace): 48 | """ Only going to pass for functions that take 1 single argument. """ 49 | res = {} 50 | try: 51 | safe_inp, clb = get_copied_input_and_callable(inp, callab) 52 | if equality_fun(clb(safe_inp), expected) or isinstance(expected, PassAnything): 53 | res = {'arity': '1', 'namespace': namespace, 'callable': callab, 54 | 'input': inp} 55 | except: 56 | pass 57 | return res 58 | 59 | 60 | def arity_one(callab, inp, expected, equality_fun, namespace, args): 61 | """ Only going to pass for functions that take 1 single argument. """ 62 | res = {} 63 | try: 64 | safe_inp, clb = get_copied_input_and_callable(inp, callab) 65 | print('FFFFFFFFFFFFFFFFWasdf') 66 | if equality_fun(clb(args), expected) or isinstance(expected, PassAnything): 67 | res = {'arity': '1', 'namespace': namespace, 'callable': callab, 68 | 'input': inp} 69 | except: 70 | pass 71 | return res 72 | 73 | 74 | def arity_starred(callab, inp, expected, equality_fun, namespace, args): 75 | """ Only going to pass for functions that take only args, and will unpack them. 76 | The 'inp' variable is ignored for that function. """ 77 | res = {} 78 | try: 79 | _, clb = get_copied_input_and_callable(inp, callab) 80 | # This is not an error; callable might not have an `x` 81 | # pylint: disable=no-value-for-parameter 82 | if equality_fun(clb(*args), expected) or isinstance(expected, PassAnything): 83 | res = {'arity': 'starred', 'namespace': namespace, 'callable': callab} 84 | except: 85 | pass 86 | return res 87 | 88 | 89 | def arity_one_starred(callab, inp, expected, equality_fun, namespace, args): 90 | """ Only going to pass for functions that take 1 single argument and also starred args. """ 91 | res = {} 92 | try: 93 | safe_inp, clb = get_copied_input_and_callable(inp, callab) 94 | if equality_fun(clb(safe_inp, *args), expected) or isinstance(expected, PassAnything): 95 | res = {'arity': '1+starred', 'namespace': namespace, 'callable': callab} 96 | except: 97 | pass 98 | return res 99 | 100 | 101 | def arity_two(callab, inp, expected, equality_fun, namespace, args): 102 | """ Only going to pass for functions that take 2 arguments. """ 103 | res = {} 104 | try: 105 | safe_inp, clb = get_copied_input_and_callable(inp, callab) 106 | if (equality_fun(clb(safe_inp, copy.copy(args)), expected) 107 | or isinstance(expected, PassAnything)): 108 | res = {'arity': '2', 'namespace': namespace, 'callable': callab} 109 | except: 110 | pass 111 | return res 112 | -------------------------------------------------------------------------------- /cant/comparison_functions.py: -------------------------------------------------------------------------------- 1 | """ Rather than doing a simple `==` comparison, this module contains functions 2 | that could be better suited to do comparisons. """ 3 | 4 | try: 5 | from itertools import izip_longest as zip_longest 6 | except ImportError: 7 | # pylint: disable=no-name-in-module 8 | from itertools import zip_longest 9 | 10 | 11 | def safe_equal(var1, var2): 12 | """ safe_equal could also work for generators. """ 13 | if hasattr(var1, '__iter__') and hasattr(var2, '__iter__'): 14 | return all(x == y for x, y in zip_longest(var1, var2)) 15 | return var1 == var2 16 | -------------------------------------------------------------------------------- /cant/get_callables.py: -------------------------------------------------------------------------------- 1 | """ 2 | Contains functions that provides ways to get important callables. 3 | Such as builtins, globals, object callable attributes and module callable attributes. 4 | """ 5 | 6 | try: 7 | import __builtin__ as builtins 8 | except ImportError: 9 | import builtins 10 | 11 | 12 | def get_builtins(exclude_list=None): 13 | """ Gets the builtins functions and filters the functions that cause disturbance. """ 14 | if exclude_list is None: 15 | exclude_list = ['input', '_dreload', 'dreload', 'open', 'help', 'license'] 16 | return [getattr(builtins, x) for x in dir(builtins) if x not in exclude_list] 17 | 18 | 19 | def protect_global_attrs(globals_dict): 20 | """ 21 | Expects `globals()` fed to it. 22 | Removes troublemakers that cause disturbance. 23 | """ 24 | attrs = [v for v in globals_dict.values() 25 | if hasattr(v, '__call__') 26 | and 'ipython' not in str(v).lower() 27 | and 'input' not in str(v).lower() 28 | and 'dreload' not in str(v).lower() 29 | and open != v 30 | and not str(v).startswith(' v documentation". 128 | #html_title = None 129 | 130 | # A shorter title for the navigation bar. Default is the same as html_title. 131 | #html_short_title = None 132 | 133 | # The name of an image file (relative to this directory) to place at the top 134 | # of the sidebar. 135 | #html_logo = None 136 | 137 | # The name of an image file (within the static path) to use as favicon of the 138 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 139 | # pixels large. 140 | #html_favicon = None 141 | 142 | # Add any paths that contain custom static files (such as style sheets) here, 143 | # relative to this directory. They are copied after the builtin static files, 144 | # so a file named "default.css" will overwrite the builtin "default.css". 145 | html_static_path = ['_static'] 146 | 147 | # Add any extra paths that contain custom files (such as robots.txt or 148 | # .htaccess) here, relative to this directory. These files are copied 149 | # directly to the root of the documentation. 150 | #html_extra_path = [] 151 | 152 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 153 | # using the given strftime format. 154 | #html_last_updated_fmt = '%b %d, %Y' 155 | 156 | # If true, SmartyPants will be used to convert quotes and dashes to 157 | # typographically correct entities. 158 | #html_use_smartypants = True 159 | 160 | # Custom sidebar templates, maps document names to template names. 161 | #html_sidebars = {} 162 | 163 | # Additional templates that should be rendered to pages, maps page names to 164 | # template names. 165 | #html_additional_pages = {} 166 | 167 | # If false, no module index is generated. 168 | #html_domain_indices = True 169 | 170 | # If false, no index is generated. 171 | #html_use_index = True 172 | 173 | # If true, the index is split into individual pages for each letter. 174 | #html_split_index = False 175 | 176 | # If true, links to the reST sources are added to the pages. 177 | #html_show_sourcelink = True 178 | 179 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 180 | #html_show_sphinx = True 181 | 182 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 183 | #html_show_copyright = True 184 | 185 | # If true, an OpenSearch description file will be output, and all pages will 186 | # contain a tag referring to it. The value of this option must be the 187 | # base URL from which the finished HTML is served. 188 | #html_use_opensearch = '' 189 | 190 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 191 | #html_file_suffix = None 192 | 193 | # Language to be used for generating the HTML full-text search index. 194 | # Sphinx supports the following languages: 195 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 196 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' 197 | #html_search_language = 'en' 198 | 199 | # A dictionary with options for the search language support, empty by default. 200 | # Now only 'ja' uses this config value 201 | #html_search_options = {'type': 'default'} 202 | 203 | # The name of a javascript file (relative to the configuration directory) that 204 | # implements a search results scorer. If empty, the default will be used. 205 | #html_search_scorer = 'scorer.js' 206 | 207 | # Output file base name for HTML help builder. 208 | htmlhelp_basename = 'cantdoc' 209 | 210 | # -- Options for LaTeX output --------------------------------------------- 211 | 212 | latex_elements = { 213 | # The paper size ('letterpaper' or 'a4paper'). 214 | #'papersize': 'letterpaper', 215 | 216 | # The font size ('10pt', '11pt' or '12pt'). 217 | #'pointsize': '10pt', 218 | 219 | # Additional stuff for the LaTeX preamble. 220 | #'preamble': '', 221 | 222 | # Latex figure (float) alignment 223 | #'figure_align': 'htbp', 224 | } 225 | 226 | # Grouping the document tree into LaTeX files. List of tuples 227 | # (source start file, target name, title, 228 | # author, documentclass [howto, manual, or own class]). 229 | latex_documents = [ 230 | (master_doc, 'cant.tex', 'cant Documentation', 231 | 'Pascal van Kooten', 'manual'), 232 | ] 233 | 234 | # The name of an image file (relative to this directory) to place at the top of 235 | # the title page. 236 | #latex_logo = None 237 | 238 | # For "manual" documents, if this is true, then toplevel headings are parts, 239 | # not chapters. 240 | #latex_use_parts = False 241 | 242 | # If true, show page references after internal links. 243 | #latex_show_pagerefs = False 244 | 245 | # If true, show URL addresses after external links. 246 | #latex_show_urls = False 247 | 248 | # Documents to append as an appendix to all manuals. 249 | #latex_appendices = [] 250 | 251 | # If false, no module index is generated. 252 | #latex_domain_indices = True 253 | 254 | 255 | # -- Options for manual page output --------------------------------------- 256 | 257 | # One entry per manual page. List of tuples 258 | # (source start file, name, description, authors, manual section). 259 | man_pages = [ 260 | (master_doc, 'cant', 'cant Documentation', 261 | [author], 1) 262 | ] 263 | 264 | # If true, show URL addresses after external links. 265 | #man_show_urls = False 266 | 267 | 268 | # -- Options for Texinfo output ------------------------------------------- 269 | 270 | # Grouping the document tree into Texinfo files. List of tuples 271 | # (source start file, target name, title, author, 272 | # dir menu entry, description, category) 273 | texinfo_documents = [ 274 | (master_doc, 'cant', 'cant Documentation', 275 | author, 'cant', 'One line description of project.', 276 | 'Miscellaneous'), 277 | ] 278 | 279 | # Documents to append as an appendix to all manuals. 280 | #texinfo_appendices = [] 281 | 282 | # If false, no module index is generated. 283 | #texinfo_domain_indices = True 284 | 285 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 286 | #texinfo_show_urls = 'footnote' 287 | 288 | # If true, do not generate a @detailmenu in the "Top" node's menu. 289 | #texinfo_no_detailmenu = False 290 | -------------------------------------------------------------------------------- /deploy.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import sh 4 | 5 | 6 | commit_count = sh.git('rev-list', ['--all']).count('\n') 7 | 8 | with open('setup.py') as f: 9 | setup = f.read() 10 | 11 | setup = re.sub( 12 | "MICRO_VERSION = '[0-9]+'", 13 | "MICRO_VERSION = '{}'".format(commit_count), setup) 14 | 15 | major = re.search("MAJOR_VERSION = '([0-9]+)'", setup).groups()[0] 16 | minor = re.search("MINOR_VERSION = '([0-9]+)'", setup).groups()[0] 17 | micro = re.search("MICRO_VERSION = '([0-9]+)'", setup).groups()[0] 18 | version = '{}.{}.{}'.format(major, minor, micro) 19 | 20 | with open('setup.py', 'w') as f: 21 | f.write(setup) 22 | 23 | with open('cant/__init__.py') as f: 24 | init = f.read() 25 | 26 | with open('cant/__init__.py', 'w') as f: 27 | f.write( 28 | re.sub('__version__ = "[0-9.]+"', 29 | '__version__ = "{}"'.format(version), init)) 30 | 31 | print(sh.python3('setup.py', ['sdist', 'bdist_wheel', 'upload'])) 32 | 33 | sh.cd('../') 34 | 35 | sh.pip3('install', ['-U', 'cant']) 36 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | .. cant documentation master file, created by 2 | sphinx-quickstart on Thu Dec 31 15:11:22 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to cant's documentation! 7 | ================================ 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | 15 | 16 | Indices and tables 17 | ================== 18 | 19 | * :ref:`genindex` 20 | * :ref:`modindex` 21 | * :ref:`search` 22 | 23 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [bdist_rpm] 5 | doc_files = README.md 6 | 7 | [wheel] 8 | universal = 1 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages 2 | from setuptools import setup 3 | 4 | # MAJOR_VERSION = '0' 5 | # MINOR_VERSION = '4' 6 | # MICRO_VERSION = '116' 7 | # VERSION = "{}.{}.{}".format(MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION) 8 | VERSION = '0.0' 9 | 10 | setup(name='cant', 11 | version=VERSION, 12 | description="Can't Remember!", 13 | url='https://github.com/kootenpv/cant', 14 | author='Pascal van Kooten', 15 | author_email='kootenpv@gmail.com', 16 | license='MIT', 17 | packages=find_packages(), 18 | classifiers=[ 19 | 'Environment :: Console', 20 | 'Intended Audience :: Developers', 21 | 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 22 | 'Operating System :: Microsoft', 23 | 'Operating System :: MacOS :: MacOS X', 24 | 'Operating System :: Unix', 25 | 'Operating System :: POSIX', 26 | 'Programming Language :: Python', 27 | 'Programming Language :: Python :: 2.7', 28 | 'Programming Language :: Python :: 3', 29 | 'Programming Language :: Python :: 3.3', 30 | 'Programming Language :: Python :: 3.4', 31 | 'Programming Language :: Python :: 3.5', 32 | 'Topic :: Software Development', 33 | 'Topic :: Software Development :: Build Tools', 34 | 'Topic :: Software Development :: Debuggers', 35 | 'Topic :: Software Development :: Libraries', 36 | 'Topic :: Software Development :: Libraries :: Python Modules', 37 | 'Topic :: System :: Software Distribution', 38 | 'Topic :: System :: Systems Administration', 39 | 'Topic :: Utilities' 40 | ], 41 | zip_safe=False, 42 | platforms='any') 43 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py35,py27,py34 3 | 4 | [testenv] 5 | # If you add a new dep here you probably need to add it in setup.py as well 6 | deps = 7 | pytest 8 | commands = py.test -v cant/tests/run_tests.py 9 | --------------------------------------------------------------------------------