# Add in pip and in python x32 + x64

dev-linux
Ivan Maslov 5 years ago
parent d55ed34256
commit 29853bd5bd

@ -0,0 +1,36 @@
About
------
`Naked <http://naked-py.com>`_ is a new Python command line application framework that is in development. The current release is a stable, testing release.
Updates
--------
Changes, updates, and brief tutorials are available on the `developer log <http://nakedpy.wordpress.com/>`_.
QuickStart Guide
------------------
The quickstart guide is available at `http://docs.naked-py.com/quickstart.html <http://docs.naked-py.com/quickstart.html>`_. It demonstrates how the available tools can be incorporated into your development workflow, spanning the entire period from an empty project directory to your first PyPI version release.
Documentation
--------------
Documentation is in development at `http://docs.naked-py.com/ <http://docs.naked-py.com/>`_
Issue Reporting
----------------
Issue reporting is available on the `GitHub repository <http://github.com/chrissimpkins/naked/issues>`_
Contribute
-----------
I would greatly appreciate feedback from anyone who is testing the framework. Feel free to contact me on Twitter (@csimpkins) if you have questions, comments, or problems. Please use the issue reporting link above for bug reports.
Example Application
-------------------
`Status <https://pypi.python.org/pypi/status>`_ was built from the ground up with the Naked Framework. If you'd like to check out the source, it is available on `GitHub <https://github.com/chrissimpkins/status/tree/master/lib/status>`_

@ -0,0 +1,61 @@
Metadata-Version: 2.0
Name: Naked
Version: 0.1.31
Summary: A command line application framework
Home-page: http://naked-py.com
Author: Christopher Simpkins
Author-email: chris@zerolabs.net
License: MIT
Keywords: python,command line,system,application,framework,CLI
Platform: any
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: Naked
Requires-Dist: requests
Requires-Dist: pyyaml
About
------
`Naked <http://naked-py.com>`_ is a new Python command line application framework that is in development. The current release is a stable, testing release.
Updates
--------
Changes, updates, and brief tutorials are available on the `developer log <http://nakedpy.wordpress.com/>`_.
QuickStart Guide
------------------
The quickstart guide is available at `http://docs.naked-py.com/quickstart.html <http://docs.naked-py.com/quickstart.html>`_. It demonstrates how the available tools can be incorporated into your development workflow, spanning the entire period from an empty project directory to your first PyPI version release.
Documentation
--------------
Documentation is in development at `http://docs.naked-py.com/ <http://docs.naked-py.com/>`_
Issue Reporting
----------------
Issue reporting is available on the `GitHub repository <http://github.com/chrissimpkins/naked/issues>`_
Contribute
-----------
I would greatly appreciate feedback from anyone who is testing the framework. Feel free to contact me on Twitter (@csimpkins) if you have questions, comments, or problems. Please use the issue reporting link above for bug reports.
Example Application
-------------------
`Status <https://pypi.python.org/pypi/status>`_ was built from the ground up with the Naked Framework. If you'd like to check out the source, it is available on `GitHub <https://github.com/chrissimpkins/status/tree/master/lib/status>`_

@ -0,0 +1,118 @@
../../Scripts/naked.exe,sha256=rMRI4H8Qgi_Gxg9r50MNWd2wsP9DnbZLKLpKzLRkRD4,92999
Naked-0.1.31.data/scripts/naked,sha256=Ps1mufxMkBG7wwaJHQ_nkMwOrPP1hTZLDH7YMNO4Y2E,285
Naked-0.1.31.dist-info/DESCRIPTION.rst,sha256=26S5QwAzVdLRvvgm9ZsFe2VsF2f6xybGklQEMt0T05s,1450
Naked-0.1.31.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Naked-0.1.31.dist-info/METADATA,sha256=z7IWAlMC3eIlNc8RlWxJ1feuDhdlQtziBOXXzcZK-c8,2341
Naked-0.1.31.dist-info/RECORD,,
Naked-0.1.31.dist-info/WHEEL,sha256=SXYYsi-y-rEGIva8sB8iKF6bAFD6YDhmqHX5hI3fc0o,110
Naked-0.1.31.dist-info/entry_points.txt,sha256=-7nL8pc5fnKhIUINYqLDa1jd3y-8jynn9u5qF9EyjqU,42
Naked-0.1.31.dist-info/pydist.json,sha256=cSetsKYPMVxYIilVGZD_wtke5QtnHkWmKGTF5uDSV10,1119
Naked-0.1.31.dist-info/top_level.txt,sha256=CG1yk0vViILO5nUzrfUqtOs-0IAsZBY1zLFGi3O-SCc,6
Naked/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
Naked/__pycache__/__init__.cpython-37.pyc,,
Naked/__pycache__/app.cpython-37.pyc,,
Naked/__pycache__/commandline.cpython-37.pyc,,
Naked/__pycache__/scratchpad.cpython-37.pyc,,
Naked/__pycache__/settings.cpython-37.pyc,,
Naked/app.py,sha256=ifeYxmcVb3aolzqZNzeQGF6rnTuJatyM3swhf68G5cc,11880
Naked/commandline.py,sha256=OJ-ktVQWZeKMTbC1r446M0m1BZidwBQMA5hpXrTMK5U,18918
Naked/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
Naked/commands/__pycache__/__init__.cpython-37.pyc,,
Naked/commands/__pycache__/args.cpython-37.pyc,,
Naked/commands/__pycache__/build.cpython-37.pyc,,
Naked/commands/__pycache__/classifier.cpython-37.pyc,,
Naked/commands/__pycache__/dist.cpython-37.pyc,,
Naked/commands/__pycache__/help.cpython-37.pyc,,
Naked/commands/__pycache__/locate.cpython-37.pyc,,
Naked/commands/__pycache__/make.cpython-37.pyc,,
Naked/commands/__pycache__/profile.cpython-37.pyc,,
Naked/commands/__pycache__/pyh.cpython-37.pyc,,
Naked/commands/__pycache__/test.cpython-37.pyc,,
Naked/commands/__pycache__/usage.cpython-37.pyc,,
Naked/commands/__pycache__/version.cpython-37.pyc,,
Naked/commands/args.py,sha256=DhW7JF2FNU0ns3P0RrcKM_aN8Pn51zfgLpa7edS7QoE,4681
Naked/commands/build.py,sha256=SDs5d6s4aCyT6zKWpJ4CgYnu8VKx910CKRe-E9mFhS8,1040
Naked/commands/classifier.py,sha256=NY4eOKDh3xiSJbJfvxN8D-YqjJrqc8qQ9e03vlPAf-A,1875
Naked/commands/dist.py,sha256=qGG1l9Z1T882WvRjBKIs-UQWSbN9efaZkK-qSYTTVV4,3287
Naked/commands/help.py,sha256=cQzrW2Axb4X_zR4JElmCaWUcE1xk2Sf9VpNO31FAimA,300
Naked/commands/locate.py,sha256=9wZ_RSCNju1hWGkrUGDOSlWTPg6cbA4_cKJuAKW4sxs,1449
Naked/commands/make.py,sha256=ikbMj3T24LExBaxgd465DBNNemqZb8y6RHHnKJTsQFY,18788
Naked/commands/profile.py,sha256=Rz_rWwdqXy6WrWrPaDCBrsVBwpJrwRCrsnHtqj-LmZ0,1700
Naked/commands/pyh.py,sha256=Bqfo513IKwPB0xY4YvtUSdvpSIetE9tW-gfTG2VoMqY,1071
Naked/commands/test.py,sha256=-T_cXmbS5BoL7wKuC6VxQ0W8-Q-dcRl64fVZsiEj75g,6720
Naked/commands/usage.py,sha256=ASp5GkdPHEd9Nz_rYNfjojI0KXmHMhmbs7ktte6LecY,305
Naked/commands/version.py,sha256=kSPrr4blhbTST1SNUEKnnD9UrP9UW7s9ehos-qiM5as,789
Naked/scratchpad.py,sha256=NJ6NYQrmzVHDHOEagFcACuSp0C2FiyKhHwpZbz7VkXE,743
Naked/settings.py,sha256=uXuD_QpSbaOL37N-p_4pk1Fsrb_uQpIl3wkg6uTR8Cw,2976
Naked/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
Naked/templates/__pycache__/__init__.cpython-37.pyc,,
Naked/templates/__pycache__/app_file.cpython-37.pyc,,
Naked/templates/__pycache__/licenses.cpython-37.pyc,,
Naked/templates/__pycache__/manifest_in_file.cpython-37.pyc,,
Naked/templates/__pycache__/profiler_file.cpython-37.pyc,,
Naked/templates/__pycache__/pypush_file.cpython-37.pyc,,
Naked/templates/__pycache__/readme_md_file.cpython-37.pyc,,
Naked/templates/__pycache__/settings_file.cpython-37.pyc,,
Naked/templates/__pycache__/setup_cfg_file.cpython-37.pyc,,
Naked/templates/__pycache__/setup_py_file.cpython-37.pyc,,
Naked/templates/app_file.py,sha256=A874Fi7TBfX2O8uMEcYvNbpUvc15C-rrFbT9MLWOL0Q,5188
Naked/templates/licenses.py,sha256=WF2mFsv8oH_xUdEJMY17oWxmjmShOagYBQRdGReIxxE,6052
Naked/templates/manifest_in_file.py,sha256=9FkG7ZHdadisE-Uh7qdI69Hn-hfACTo7II8LG23bGBY,109
Naked/templates/profiler_file.py,sha256=XSxC4nBng26j7NmmmOXHz2wZ4702FpAGntaNeQ8WGLw,1530
Naked/templates/pypush_file.py,sha256=RUndgzH4y9LhYgka1oTvVB__yfvXdysNdK7qOzwONyE,586
Naked/templates/readme_md_file.py,sha256=njESHWuw5heC2EjRe8m7BgY1Wv2gXMUSnf0SjXLLpB4,104
Naked/templates/settings_file.py,sha256=bkCfQE_qp-tdXCwBdII_4IqaO2U5XJUyh-QvTypOW1s,1179
Naked/templates/setup_cfg_file.py,sha256=Bl-AkoQWe2Ath13L68J6pnzVPyz0FRmr7vCKIdyeAkU,107
Naked/templates/setup_py_file.py,sha256=Z2c0FpDTKnRP2txJB7fSCEkD17CnyTgIFOLCRlR_kgs,1769
Naked/toolshed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
Naked/toolshed/__pycache__/__init__.cpython-37.pyc,,
Naked/toolshed/__pycache__/benchmarking.cpython-37.pyc,,
Naked/toolshed/__pycache__/casts.cpython-37.pyc,,
Naked/toolshed/__pycache__/file.cpython-37.pyc,,
Naked/toolshed/__pycache__/git.cpython-37.pyc,,
Naked/toolshed/__pycache__/ink.cpython-37.pyc,,
Naked/toolshed/__pycache__/iter.cpython-37.pyc,,
Naked/toolshed/__pycache__/network.cpython-37.pyc,,
Naked/toolshed/__pycache__/python.cpython-37.pyc,,
Naked/toolshed/__pycache__/shell.cpython-37.pyc,,
Naked/toolshed/__pycache__/state.cpython-37.pyc,,
Naked/toolshed/__pycache__/system.cpython-37.pyc,,
Naked/toolshed/__pycache__/types.cpython-37.pyc,,
Naked/toolshed/benchmarking.py,sha256=Dn5EXmR_wiAtG-mqWmBFQJ_i749_-hZ1-PxEBwSsAwQ,17235
Naked/toolshed/c/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
Naked/toolshed/c/__pycache__/__init__.cpython-37.pyc,,
Naked/toolshed/c/__pycache__/setup.cpython-37.pyc,,
Naked/toolshed/c/benchmarking.c,sha256=UDYMyo3eaMQB0cc28AfkyePULEQuvtqaFeZWK9DgzLM,880286
Naked/toolshed/c/benchmarking.pyx,sha256=Dn5EXmR_wiAtG-mqWmBFQJ_i749_-hZ1-PxEBwSsAwQ,17235
Naked/toolshed/c/build.sh,sha256=LEtZwrw9A6Tx4Z-tSf4kjSKFLTyX97xs5uoJBcitB8w,36
Naked/toolshed/c/casts.c,sha256=bgEj7BmtKcHmMd1W5qIcOC8_KH5BP66z3x_tLMF4N7I,227012
Naked/toolshed/c/casts.pyx,sha256=Jq6Wt3re7fS1-ry9uD4B38yfGi-CbwhxsLZl8HODNis,4813
Naked/toolshed/c/cstate.c,sha256=qTe_e46gCtGYUdgt--ulHl9NaE4T_K7j7D5V93AUawA,134375
Naked/toolshed/c/cstate.pyx,sha256=5EDxBjneKCRyEwQslZspCLl1A2i7dMtEIu1mfM75qpo,1089
Naked/toolshed/c/cythonize.sh,sha256=-Fy5q0oMAqOKj5aFDfRuaQUPpqGrKCSDatPdFt0d_zI,256
Naked/toolshed/c/file.c,sha256=DtLXGU5JzSJCDzC8tZxM0k_ucf3ONwepxB6Q1fipL1I,623270
Naked/toolshed/c/file.pyx,sha256=ru3r-7QVgTubZ3sbbNO_jqF0o_qfJBYzfGSXPL7X18c,19965
Naked/toolshed/c/ink.c,sha256=L0brN1oD-airTLFV378wfkLZ6r1MgAHozsl5GlaMjdo,185313
Naked/toolshed/c/ink.pyx,sha256=r73b8N46boGa7Cerw88uPGk3luNQWgoE7SS2Ru4k0ys,5460
Naked/toolshed/c/network.c,sha256=ft-bqnr3ervphD1IXiXN9krqZ6GJPmLA2OdrH9N8CaE,525661
Naked/toolshed/c/network.pyx,sha256=-NX-7RFbN2DAsOdW4mvtNYnCP1GVHx8CQubmL7wjaQg,19549
Naked/toolshed/c/python.c,sha256=E2rAQDq1pVgehMwDQenNF5ZZIBdpauHKA5TKFPWxBSk,111860
Naked/toolshed/c/python.pyx,sha256=WTST5lYVqizCtAXbHZqd5HGOO9ywCCxP8dbzLB2tbcM,2157
Naked/toolshed/c/setup.py,sha256=oOuer8J1ZqJxxWhXiYzmtPmyeaQy2FNQNp1c99AzF4U,654
Naked/toolshed/c/shell.c,sha256=1CrgdwUQsHkkzKKvVYfmZoA6OaG23xqriKiO0a_secI,376470
Naked/toolshed/c/shell.pyx,sha256=efpvnnT8cu6xXOGvhqd2MpMCiv2Z4Eau8VjRp9pAYSc,12629
Naked/toolshed/c/system.c,sha256=bSRfuYZe8C5nIk2WZrcXm5eYeJZ-3OwD5gzx2jwUPtE,620280
Naked/toolshed/c/system.pyx,sha256=bPjCcxkWLuS-X5CZgUC8Rkilc2x-S-X2e9MkvzEf-xw,24684
Naked/toolshed/c/types.c,sha256=STvR0OE_PLkGros1B0vjepCZdhClEjjaCEkqyuZNMOc,1240797
Naked/toolshed/c/types.pyx,sha256=ep0NkR_OFbmp96KaAx5mxPYYUTtc7V6L1qSkaLS_oq8,44721
Naked/toolshed/casts.py,sha256=elaNlp0hBRJ_bFPTX-4eYB90gmPrbVPz_6TY4HFrbc8,5126
Naked/toolshed/file.py,sha256=FnYhoVCgnTYU-WjedCLJFgsd9UkvbvJNt5J-ftWML3E,19941
Naked/toolshed/git.py,sha256=WAX_snuOFpVIIBPRsIZXva24wK67MEBNZE5eST4fSDg,79
Naked/toolshed/ink.py,sha256=9i_ZJpgpXtLqDs32OFGoeiNU7Ajo7xwKmI9FdCCcMt8,5436
Naked/toolshed/iter.py,sha256=yUalH_tyXYtEqsFDuy2n5ZfussXmdFunzgA4W7Ydz9M,500
Naked/toolshed/network.py,sha256=VpTSm6XQy2Pm_-atsqyt5vd9ZMnYFrJsfJhPwZ2R-js,19525
Naked/toolshed/python.py,sha256=lY-Nb8nymApIyI4pWJNHst11VA8IJygBF62ASnjg9Yk,2158
Naked/toolshed/shell.py,sha256=8hAdzS15TTzofHr2mRCLpf7ThTNiDVouQjWI18LSCNg,12605
Naked/toolshed/state.py,sha256=_PnDMY5Vws9JXN6VdoQlNWwhZ1EwoiwUDu-qjl_Nmk4,1061
Naked/toolshed/system.py,sha256=IeJhooglhxKbKiG5NYw6_ye8MeRKNSY5nOz1BZCZBNk,24660
Naked/toolshed/types.py,sha256=xd_Bu_fKu0FbULD4EvwQ_OBYWMuBVj5r4pEx4Wm7riA,44532

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.22.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

@ -0,0 +1 @@
{"license": "MIT", "exports": {"console_scripts": {"naked": "Naked.app:main"}}, "document_names": {"description": "DESCRIPTION.rst"}, "name": "Naked", "metadata_version": "2.0", "contacts": [{"role": "author", "email": "chris@zerolabs.net", "name": "Christopher Simpkins"}], "generator": "bdist_wheel (0.22.0)", "commands": {"wrap_console": {"naked": "Naked.app:main"}}, "summary": "A command line application framework", "project_urls": {"Home": "http://naked-py.com"}, "platform": "any", "run_requires": [{"requires": ["Naked", "requests", "pyyaml"]}], "version": "0.1.31", "keywords": "python,command line,system,application,framework,CLI", "classifiers": ["Intended Audience :: Developers", "Natural Language :: English", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Topic :: Software Development :: Libraries :: Python Modules"], "extras": []}

@ -0,0 +1,229 @@
#!/usr/bin/env python
# encoding: utf-8
#------------------------------------------------------------------------------
# Naked | A Python command line application framework
# Copyright 2014 Christopher Simpkins
# MIT License
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------------
# c.cmd = Primary command (<executable> <primary command>)
# c.cmd2 = Secondary command (<executable> <primary command> <secondary command>)
#
# c.option(option_string, [bool argument_required]) = test for option with optional test for positional arg to the option
# c.option_with_arg(option_string) = test for option and mandatory positional argument to option test
# c.flag(flag_string) = test for presence of a "--option=argument" style flag
#
# c.arg(arg_string) = returns the next positional argument to the arg_string argument
# c.flag_arg(flag_string) = returns the flag assignment for a "--option=argument" style flag
#------------------------------------------------------------------------------------
# Application start
def main():
import sys
from Naked.commandline import Command
#from Naked.toolshed.state import StateObject
from Naked.toolshed.system import stderr
#------------------------------------------------------------------------------------------
# [ Instantiate command line object ]
# used for all subsequent conditional logic in the CLI application
#------------------------------------------------------------------------------------------
c = Command(sys.argv[0], sys.argv[1:])
#------------------------------------------------------------------------------
# [ Instantiate state object ]
#------------------------------------------------------------------------------
#state = StateObject()
#------------------------------------------------------------------------------------------
# [ Command Suite Validation ] - early validation of appropriate command syntax
# Test that user entered a primary command, print usage if not
#------------------------------------------------------------------------------------------
if not c.command_suite_validates():
from Naked.commands.usage import Usage
Usage().print_usage()
sys.exit(1)
#------------------------------------------------------------------------------------------
# [ PRIMARY COMMAND LOGIC ]
# Test for primary commands and handle them
#------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ args ] - identify the parsed arguments for a command string (2)= help
#------------------------------------------------------------------------------
if c.cmd == "args":
if c.cmd2 == "help":
from Naked.commands.args import help as args_help
args_help()
elif c.argc > 0: # there is an argument to where that is not help
from Naked.commands.args import Args
a = Args(c.arg_to_cmd)
a.run()
else:
stderr("The args command requires an example command as an argument. Use 'naked args help' for more information.", 1)
#------------------------------------------------------------------------------
# [ build ] - build the C code in the Naked library (2)= help
#------------------------------------------------------------------------------
elif c.cmd == "build":
if c.cmd2 == "help":
from Naked.commands.build import help as build_help
build_help()
else:
from Naked.commands.build import compile_c_code
import os, inspect
abs_dirpath = os.path.join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))), "toolshed", "c")
compile_c_code(abs_dirpath) # function calls exit status code
#------------------------------------------------------------------------------
# [ classify ] - search Python application classifiers and display to user (args)-search string
#------------------------------------------------------------------------------
elif c.cmd == "classify":
if c.cmd2 == "help":
from Naked.commands.classifier import help as classifier_help
classifier_help()
else:
if c.second: # if search string was given
search_string = c.second
else:
search_string = "" # absence of search string detected in Classifier, defaults to the entire list instead of search
from Naked.commands.classifier import Classifier
c = Classifier(search_string)
c.run()
#------------------------------------------------------------------------------
# [ dist ] - distribute source files to PyPI (2)=register, sdist, swheel, wheel, win, all, help
#------------------------------------------------------------------------------
elif c.cmd == "dist":
if c.argc > 1:
from Naked.commands.dist import Dist
d = Dist()
if c.cmd2 == "register": # python setup.py register
d.run('register')
elif c.cmd2 == "sdist": # python setup.py sdist upload
d.run('sdist')
elif c.cmd2 == "swheel": # python setup.py sdist bdist_wheel upload
d.run('swheel')
elif c.cmd2 == "wheel": # python setup.py bdist_wheel upload
d.run('wheel')
elif c.cmd2 == "win": # python setup.py bdist_wininst upload
d.run('win')
elif c.cmd2 == "all": # python setup.py sdist bdist_wheel bdist_wininst upload
d.run('all')
elif c.cmd2 == "help": # help for command
from Naked.commands.dist import help as dist_help
dist_help()
else:
stderr("The naked dist secondary command was not recognized. Use 'naked dist help' for more information.", 1)
else:
stderr("Please enter a secondary command", 1)
#------------------------------------------------------------------------------
# [ locate ] - locate Naked project files (2)= main, settings, setup, help
#------------------------------------------------------------------------------
elif c.cmd == "locate":
from Naked.commands.locate import Locator
if c.cmd2 == "help":
from Naked.commands.locate import help as locate_help
locate_help()
elif c.cmd2 == "main":
l = Locator('main')
elif c.cmd2 == "settings":
l = Locator('settings')
elif c.cmd2 == "setup":
l = Locator('setup')
else:
l = Locator('') #handles error report to user
#------------------------------------------------------------------------------
# [ make ] - make a new Naked project (2)=help (args)=project name
#------------------------------------------------------------------------------
elif c.cmd == "make":
from Naked.commands.make import MakeController
if c.cmd2 == "help":
from Naked.commands.make import help as make_help
make_help()
if c.arg1: # arg1 is not help so use it as the argument to the make command
m = MakeController(c.arg1)
else:
m = MakeController(None)
m.run()
#------------------------------------------------------------------------------
# [ profile ] - run the profiler.py file in the Naked project (2)=help
#------------------------------------------------------------------------------
elif c.cmd == "profile":
if c.cmd2 == "help":
from Naked.commands.profile import help as profile_help
profile_help()
else:
from Naked.commands.profile import Profiler
p = Profiler()
p.run()
#------------------------------------------------------------------------------
# [ pyh ] - help for python built-in library modules, classes, methods, functions
#------------------------------------------------------------------------------
elif c.cmd == "pyh":
if c.cmd2 == "help":
from Naked.commands.pyh import pyh_help
pyh_help()
else:
if c.argc > 1:
from Naked.commands.pyh import python_help
python_help(c.arg1)
else:
stderr("Please enter a query term with the pyh command. Use 'naked pyh help' for more information.", 1)
#------------------------------------------------------------------------------
# [ test ] - Run unit tests on the project (2)= help,nose,pytest,tox,unittest (see help for args)
#------------------------------------------------------------------------------
elif c.cmd == "test":
if c.argc > 1:
if c.cmd2 == "help":
from Naked.commands.test import help as tox_help
tox_help()
elif c.cmd2 == "nose":
from Naked.commands.test import NoseTester
n = NoseTester()
n.run()
elif c.cmd2 == "pytest":
from Naked.commands.test import PyTester
p = PyTester()
p.run()
elif c.cmd2 == "tox":
from Naked.commands.test import ToxTester
if c.arg2: #user specified a python version to run with one of the tox version defs
t = ToxTester(c.arg2) #instantiate with the python version
else:
t = ToxTester()
t.run()
elif c.cmd2 == "unittest":
from Naked.commands.test import UnitTester
if c.arg2:
t = UnitTester(c.arg2)
t.run()
else:
stderr("Please include a unit test file path. Use 'naked test help' for more information.", 1)
else:
stderr("The secondary command was not recognized. Use 'naked test help' for more information.", 1)
else:
stderr("Please include a secondary command with the 'naked test' command. Use 'naked dist help' for more information.", 1)
#------------------------------------------------------------------------------------------
# [ NAKED FRAMEWORK COMMANDS ]
# Naked framework provides default help, usage, and version commands for all applications
# --> settings for user messages are assigned in the lib/PROJECT/settings.py file
#------------------------------------------------------------------------------------------
elif c.help(): # User requested naked help (help.py module in commands directory)
from Naked.commands.help import Help
Help().print_help()
elif c.usage(): # user requested naked usage info (usage.py module in commands directory)
from Naked.commands.usage import Usage
Usage().print_usage()
elif c.version(): # user requested naked version (version.py module in commands directory)
from Naked.commands.version import Version
Version().print_version()
#------------------------------------------------------------------------------------------
# [ DEFAULT MESSAGE FOR MATCH FAILURE ]
# Message to provide to the user when all above conditional logic fails to meet a true condition
#------------------------------------------------------------------------------------------
else:
print("Could not complete the command that you entered. Please try again.")
sys.exit(1) #exit
if __name__ == '__main__':
main()

@ -0,0 +1,371 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
from Naked.settings import debug as DEBUG_FLAG
#####################################################################
# [ Command class ]
# Command line command string object
# argv = list of command line arguments and options
# argc = count of command line arguments and options
# arg0 = first positional argument to command
# arg1 = second positional argument to command
# arglp = last positional argument to command
# cmd = primary command for command suite application (=arg0)
# cmd2 = secondary command for command suite application (=arg1)
# snippet for py block comment = #py + TAB
#####################################################################
class Command:
def __init__(self, app_path, argv):
self.argobj = Argument(argv) # create an Argument obj
self.optobj = Option(argv) # create an Option obj
self.app = app_path # path to application executable file
self.argv = argv # list of the command arguments argv[0] is first argument
self.argc = len(argv) # length of the argument list
self.arg0 = self.argobj._getArg(0) # define the first positional argument
self.arg1 = self.argobj._getArg(1) # define the second positional argument
self.arg2 = self.argobj._getArg(2) # define the third postitional argument
self.arg3 = self.argobj._getArg(3) # define the fourth positional argument
self.arg4 = self.argobj._getArg(4) # define the fifth positional argument
self.arglp = self.argobj._getArg(len(argv) - 1) # define the last positional argument
self.first = self.arg0
self.second = self.arg1
self.third = self.arg2
self.fourth = self.arg3
self.fifth = self.arg4
self.last = self.arglp
self.arg_to_exec = self.arg0 # argument to the executable
self.arg_to_cmd = self.arg1 # argument to the primary command
self.cmd = self.arg0 # define the primary command variable as the first positional argument (user dependent & optional, may be something else)
self.cmd2 = self.arg1 # define the secondary command variable as the second positional argument (user dependent & optional, may be something else)
self.options = self.option_exists() # test for presence of at least one option (boolean)
self.flags = self.flag_exists() # test for presence of at least one flag (boolean)
#------------------------------------------------------------------------------
# [ app_validates_args method ] (boolean)
# Test whether app validates on the criterion arguments (argc) > 0, i.e. there is at least one argument to the executable
#------------------------------------------------------------------------------
def app_validates_args(self):
try:
if self.argc > 0:
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Validation of application error in the app_validates() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------------------
# [ arg method ] (string)
# Return the NEXT positional argument to a command line object (e.g. an option that requires an argument)
# arg_recipient = the positional argument (at position n) to test for next positional argument
# returns next positional argument string at position n + 1
#------------------------------------------------------------------------------------------
def arg(self, arg_recipient):
try:
recipient_position = self.argobj._getArgPosition(arg_recipient)
return self.argobj._getArgNext(recipient_position)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing argument with arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------------------
# [ command method ] (boolean)
# Test that the command includes requested primary command suite command (cmd_str parameter)
# cmd_str = the command string to test for in command
# arugment_required = boolean - is an argument to this command required (default = no)?
# returns boolean for presence of the cmd_str
#------------------------------------------------------------------------------------------
def command(self, cmd_str):
try:
if (cmd_str == self.cmd):
return True
else:
return False # if command is missing, return false
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing command with command() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [ command_arg method ] (string)
# Return the argument to the primary command as a string
#------------------------------------------------------------------------------
def command_arg(self):
try:
return self.arg1
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing command argument with command_arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [ command2_arg method ] (string)
# Return the argument to the secondary command as a string
#------------------------------------------------------------------------------
def command2_arg(self):
try:
return self.arg2
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing command argument with command_arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------------------
# [ command_with_argument method ] (boolean)
# Test that the command includes requested primary command suite command (cmd_str parameter) and argument to it
# cmd_str = the command string to test for in command
# returns boolean for presence of the cmd_str AND presence of argument to the command
#------------------------------------------------------------------------------------------
def command_with_argument(self, cmd_str):
try:
if (cmd_str == self.cmd):
argument_to_cmd = self.argobj._getArgNext(0)
if argument_to_cmd == "": # if the argument is missing, then return false
return False
else:
return True
else:
return False # if command is missing return false
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing command and argument with command_with_argument() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------------------
# [ command_suite_validates method ] (boolean)
# Test that there is a primary command in a command suite application (to be used at the top level of logic for command line application)
# returns boolean for presence of the primary command
#------------------------------------------------------------------------------------------
def command_suite_validates(self, accept_options_as_argument = True):
try:
if self.argc > 0:
if self.arg0.startswith("-") and accept_options_as_argument == False:
return False # if no command and option present, return False
else:
return True # if a primary command present, return True
else:
return False # if user only entered the application name, return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Command suite validation error with the command_suite_validation() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [ flag method ] (boolean)
# Test for presence of flag in the command
#------------------------------------------------------------------------------
def flag(self, flag_string):
try:
for match_string in self.optobj: #iterate through the options and attempt to match beginning of option to the requested flag
if match_string.startswith(flag_string):
return True
else:
pass
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing flags with the flag() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [flag_arg method] (string)
# Return the argument string assigned to a flag
#------------------------------------------------------------------------------
def flag_arg(self, flag_string):
try:
for match_string in self.optobj:
if match_string.startswith(flag_string) and '=' in match_string:
flag_list = match_string.split("=") #split the flag on the equal symbol = list with [option, argument]
return flag_list[1] #return the argument to the flag option
else:
pass
return "" # return an empty string if unable to parse the argument
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing flags with the flag_arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [ flag_exists method ] (boolean)
# Test for the presence of a flag style option (--flag=argument) in the command
#------------------------------------------------------------------------------
def flag_exists(self):
try:
for item in self.optobj:
if '=' in item: #test for presence of an = symbol in the option
return True # if present return True
break
return False # if didn't match across all options, return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing flags with the flag_arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------------------
# [ option method ] (boolean)
# Test that the command includes an option (option_string parameter)
# option_string = the option string to test for in the command
# arugment_required = boolean - is an argument to this option required (default = no)?
# returns boolean for presence of the cmd_str
#------------------------------------------------------------------------------------------
def option(self, option_string, argument_required = False):
try:
if (option_string in self.optobj):
argument_to_option = self.argobj._getArgNext(self.argobj._getArgPosition(option_string))
if argument_required and ( argument_to_option == "" or argument_to_option.startswith("-") ):
return False
else:
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing option with option() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [ option_arg method ] (string)
# Return the argument string to an option
#------------------------------------------------------------------------------
def option_arg(self, option_string):
try:
return self.argobj._getArgNext(self.argobj._getArgPosition(option_string))
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error returning argument to option with option_arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------------------
# [ option_with_arg method ] (boolean)
# Test that the command includes an option (option_string parameter) and argument to that option
# option_string = the option string to test for in the command
# arugment_required = boolean - is an argument to this option required (default = yes)?
# returns boolean for presence of the option_string AND the argument
#------------------------------------------------------------------------------------------
# test that command includes an option (option_string parameter) that includes an argument (=option(option_string, True))
def option_with_arg(self, option_string, argument_required = True):
try:
if (option_string in self.optobj):
argument_to_option = self.argobj._getArgNext(self.argobj._getArgPosition(option_string))
if argument_required and ( argument_to_option == "" or argument_to_option.startswith("-") ):
return False # argument is either missing or is another option, return false
else:
return True
else:
return False # option is not present
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error parsing option and argument with option_with_arg() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# [ option_exists method ] (boolean)
# Test whether there are any options in the command string
# returns boolean value for test "Is there at least one option?"
#------------------------------------------------------------------------------
def option_exists(self):
try:
if len(self.optobj) > 0:
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Error testing for the presence of at least one option with option_exists() method (Naked.commandline.py).")
raise e
#------------------------------------------------------------------------------
# Naked provides the following commands for all applications that use the framework:
# -- help
# -- usage
# -- version
# These methods are accessed from the app.py module, main() as method calls on the command line object
# Parsing logic is coded below
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Help Command/Option Handler
#------------------------------------------------------------------------------
def help(self):
if ( (self.option("--help")) or (self.cmd == "help") or (self.option("-h")) ):
return True
else:
return False
#------------------------------------------------------------------------------
# Usage Command/Option Handler
#------------------------------------------------------------------------------
def usage(self):
if ( (self.option("--usage")) or (self.cmd == "usage") ):
return True
else:
return False
#------------------------------------------------------------------------------
# Version Command/Option Handler
#------------------------------------------------------------------------------
def version(self):
if ( (self.option("--version")) or (self.cmd == "version") or (self.option("-v"))):
return True
else:
return False
#------------------------------------------------------------------------------
# print the arguments with their corresponding argv list position to std out
#------------------------------------------------------------------------------
def show_args(self):
x = 0
for arg in self.argv:
print("argv[" + str(x) + "] = " + arg)
x = x + 1
#------------------------------------------------------------------------------
# [ Argument Class ]
# all command line arguments (object inherited from Python list)
#------------------------------------------------------------------------------
class Argument(list):
def __init__(self, argv):
self.argv = argv
list.__init__(self, self.argv)
# return argument at position specified by the 'position' parameter
def _getArg(self, position):
if ( self.argv ) and ( len(self.argv) > position ):
return self.argv[position]
else:
return ""
# return position of user specified argument in the argument list
def _getArgPosition(self, test_arg):
if ( self.argv ):
if test_arg in self.argv:
return self.argv.index(test_arg)
else:
return -1
# return the argument at the next position following a user specified positional argument (e.g. for argument to an option in cmd)
def _getArgNext(self, position):
if len(self.argv) > (position + 1):
return self.argv[position + 1]
else:
return ""
#------------------------------------------------------------------------------
# [ Option Class ]
# Command line options (object inherited from Python list)
# Definition: string that begins with "-" (i.e. can be -h or --long)
#------------------------------------------------------------------------------
class Option(list):
def __init__(self, argv):
self.argv = argv
list.__init__(self, self._make_option_list())
# make a list of the options in the command (defined as anything that starts with "-" character)
def _make_option_list(self):
optargv = []
for x in self.argv:
if x.startswith("-"):
optargv.append(x)
return optargv

@ -0,0 +1,120 @@
#!/usr/bin/env python
# encoding: utf-8
from Naked.commandline import Command
from Naked.toolshed.system import exit_success
import shlex
class Args:
def __init__(self, command_string):
self.com_string = command_string
def run(self):
cmd_list = shlex.split(self.com_string)
c = Command(cmd_list[0], cmd_list[1:])
print(' ')
print("•naked• Assuming that your Command object is instantiated as an instance named 'c', the command that you entered would be parsed as follows:")
print(' ')
print('Application')
print('-----------')
print('c.app = ' + c.app)
print(' ')
print('Argument List Length')
print('--------------------')
print('c.argc = ' + str(c.argc))
print(' ')
print('Argument List Items')
print('-------------------')
print('c.argobj = ' + str(c.argobj))
print(' ')
print('Arguments by Zero Indexed Start Position')
print('----------------------------------------')
print('c.arg0 = ' + c.arg0)
print('c.arg1 = ' + c.arg1)
print('c.arg2 = ' + c.arg2)
print('c.arg3 = ' + c.arg3)
print('c.arg4 = ' + c.arg4)
print(' ')
print('Arguments by Named Position')
print('---------------------------')
print('c.first = ' + c.first)
print('c.second = ' + c.second)
print('c.third = ' + c.third)
print('c.fourth = ' + c.fourth)
print('c.fifth = ' + c.fifth)
print(' ')
print('Last Positional Argument')
print('------------------------')
print('c.arglp = ' + c.arglp)
print('c.last = ' + c.last)
print(' ')
print('Primary & Secondary Commands')
print('----------------------------')
print('c.cmd = ' + c.cmd)
print('c.cmd2 = ' + c.cmd2)
print(' ')
print('Option Exists Tests')
print('------------------')
print('c.option_exists() = ' + str(c.option_exists()))
print('c.options = ' + str(c.options))
print(' ')
print('Option Argument Assignment')
print('--------------------------')
if c.option_exists(): # if there are options, iterate through and print arguments to them
non_flag_options = False
for x in range(len(c.optobj)):
if '=' in c.optobj[x]:
continue # don't print flags, they are handled below
else:
print('c.arg("' + c.optobj[x] + '") = ' + c.arg(c.optobj[x]))
non_flag_options = True
if not non_flag_options:
print("There are no short or long options in the command.")
else: # otherwise, inform user that there are no options
print("There are no short options, long options, or flags in your command.")
print(' ')
print('Flag Exists Tests')
print('----------------')
print('c.flag_exists() = ' + str(c.flag_exists()))
print('c.flags = ' + str(c.flags))
print(' ')
print('Flag Argument Assignment')
print('------------------------')
if c.flag_exists():
for y in c.optobj:
if '=' in y:
the_flag = y.split('=')[0]
print('c.flag_arg("' + the_flag + '") = ' + c.flag_arg(the_flag))
else: # provide message if there are no flags
print("There are no flag style arguments (--flag=argument) in your command.")
exit_success()
#------------------------------------------------------------------------------
# [ help function ] - help for the where command
#------------------------------------------------------------------------------
def help():
from Naked.toolshed.system import exit_success
help_string = """
Naked args Command Help
=======================
The args command displays information about the data that are parsed from a command string to Command object attributes and that are obtained from Command object methods. It is intended to help with the design of your application logic when you use the Naked command line parser.
USAGE
naked args '<command statement>'
The command statement is a mandatory argument to the command. It should include a complete command as it would be entered on the command line, including the executable. The argument should be completely enclosed within quotes.
SECONDARY COMMANDS
none
OPTIONS
none
EXAMPLE
naked args 'testapp save somestring --unicode -s --name=file.txt'"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,40 @@
#!/usr/bin/env python
# encoding: utf-8
from Naked.toolshed.system import exit_success
#------------------------------------------------------------------------------
# [ compile_c_code function ] (--none--)
# compile C files in the lib/Naked/toolshed/c directory
#------------------------------------------------------------------------------
def compile_c_code(abs_dirpath):
from Naked.toolshed.shell import execute
from os import chdir
chdir(abs_dirpath)
print('•naked• Compiling the C source library files...')
success = execute("python setup.py build_ext --inplace")
if success:
print(' ')
print('•naked• C source code compile complete.')
exit_success()
def help():
help_string = """
Naked build Command Help
========================
The build command compiles the Naked C libraries. This requires an installed C compiler.
USAGE
naked build
SECONDARY COMMANDS
none
OPTIONS
none"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,60 @@
#!/usr/bin/env python
# encoding: utf-8
from Naked.toolshed.system import exit_success
class Classifier:
def __init__(self, search_string):
self.needle = search_string
self.url = 'https://pypi.python.org/pypi?%3Aaction=list_classifiers'
def run(self):
from Naked.toolshed.network import HTTP
http = HTTP(self.url) # use the python.org url for the classifier list
print('•naked• Pulling the classifier list from python.org...')
res = http.get() # get the list
test_list = res.split('\n') # split on newlines
if self.needle == "": # user did not enter a search string, print the entire list
print("•naked• You did not provide a search string. Here is the entire list:")
print(' ')
for item in test_list:
print(item)
else: # user entered a search string, find it
lower_needle = self.needle.lower()
print("•naked• Performing a case insensitive search for '" + self.needle + "'")
print(' ')
filtered_list = [ x for x in test_list if lower_needle in x.lower() ] #case insensitive match for the search string
for item in filtered_list:
print(item)
exit_success() # exit with zero status code
def help():
help_string = """
Naked classify Command Help
===========================
The classify command performs a case-insensitive search of the PyPI application classifier list and displays the results.
USAGE
naked classify [search string]
The search string argument is optional. If you do not include a search string, the entire classifier list is displayed.
SECONDARY COMMANDS
none
OPTIONS
none
EXAMPLES
naked classify
naked classify Internet
"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,93 @@
#!/usr/bin/env python
# encoding: utf-8
import os
from Naked.toolshed.system import file_exists, stderr, exit_success
from Naked.toolshed.shell import run as shell_run
class Dist:
def __init__(self):
self.register = "python setup.py register"
self.sdist = "python setup.py sdist upload"
self.wheel = "python setup.py bdist_wheel upload"
self.swheel = "python setup.py sdist bdist_wheel upload"
self.win = "python setup.py bdist_wininst upload"
self.all = "python setup.py sdist bdist_wheel bdist_wininst upload"
#------------------------------------------------------------------------------
# [ run method ] - iterates through up to 6 directories above current working
# directory and then runs command if setup.py found
#------------------------------------------------------------------------------
def run(self, command):
setuppy_found = False
for i in range(6): # navigate up at most 4 directory levels to search for the setup.py file
if not self._is_setup_py_at_this_level():
os.chdir(os.pardir)
else:
setuppy_found = True
self._run_dist_command(command)
break
if not setuppy_found:
stderr("Unable to locate the setup.py file for your project. Please confirm that you are in your project directory and try again.", 1)
else:
exit_success()
# search for setup.py file
def _is_setup_py_at_this_level(self):
if file_exists('setup.py'):
return True
else:
return False
# run the user requested command
def _run_dist_command(self, the_command):
if the_command in "register":
print('•naked• Running register...')
shell_run(self.register)
elif the_command in "sdist":
print('•naked• Running sdist...')
shell_run(self.sdist)
elif the_command in "wheel":
print('•naked• Running wheel...')
shell_run(self.wheel)
elif the_command in "swheel":
print('•naked• Running swheel...')
shell_run(self.swheel)
elif the_command in "win":
print('•naked• Running win...')
shell_run(self.win)
elif the_command in "all":
print('•naked• Running all...')
shell_run(self.all)
else:
stderr("Unrecognized command. Use 'naked dist help' to view the supported commands.", 1)
def help():
help_string = """
Naked dist Command Help
=======================
The dist secondary commands run the standard distutils 'python setup.py <command>' source/binary distribution commands.
USAGE
naked dist <secondary_command>
SECONDARY COMMANDS python setup.py <command(s)>
all sdist bdist_wheel bdist_wininst upload
register register
sdist sdist upload
swheel sdist bdist_wheel upload
wheel bdist_wheel upload
win bdist_wininst upload
OPTIONS
none
EXAMPLES
naked dist register
naked dist sdist"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,17 @@
#!/usr/bin/env python
# encoding: utf-8
import Naked.settings
from Naked.toolshed.system import exit_success
class Help:
def __init__(self):
self.help = Naked.settings.help
def print_help(self):
print(self.help)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,51 @@
#!/usr/bin/env python
# encoding: utf-8
import os
from Naked.toolshed.system import stderr, exit_success
class Locator:
def __init__(self, needle):
self.needle = needle
self.location = self._display_location()
def _display_location(self):
if self.needle == 'main':
main_path = os.path.join('<PROJECT>', 'lib', '<PROJECT>', 'app.py')
print("app.py : " + main_path)
exit_success()
elif self.needle == "settings":
settings_path = os.path.join('<PROJECT>', 'lib', '<PROJECT>','settings.py')
print("settings.py : " + settings_path)
exit_success()
elif self.needle == "setup":
setup_path = os.path.join('<PROJECT>', 'setup.py')
print("setup.py : " + setup_path)
exit_success()
else:
stderr("Unable to process the command. Use 'naked locate help' for more information.", 1)
def help():
help_string = """
Naked locate Command Help
=========================
The locate command identifies the file path to commonly used files in your project directory.
USAGE
naked locate <argument>
SECONDARY COMMANDS
main - the main application script file, app.py
setup - the setup.py file
settings - the project settings files, settings.py
OPTIONS
none
EXAMPLE
naked locate main"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,388 @@
#!/usr/bin/env python
# encoding: utf-8
import Naked.toolshed.system as system
import Naked.toolshed.python as python
import Naked.toolshed.file as nfile
import Naked.toolshed.ink as ink
from Naked.toolshed.types import XDict, XString
from Naked.toolshed.system import make_dirs, make_path, exit_success
import datetime
import sys
## TODO: Check for a local settings file (appname.yaml)
## TODO: make directories and files
#------------------------------------------------------------------------------
# [ MakeController class ]
# Top level logic for the make command
#------------------------------------------------------------------------------
class MakeController:
def __init__(self, app_name):
self.app_name = app_name
def run(self):
if self.app_name == None:
i = InfoCompiler(None)
data_container = i.getSetupFileInfo()
else:
i = InfoCompiler(self.app_name)
data_container = i.getUserInfo()
db = DirectoryBuilder(data_container)
db.build()
fb = FileBuilder(data_container)
if fb.build_and_write(): # file writes were successful
main_script_path = make_path(data_container.app_name, 'lib', data_container.app_name, 'app.py')
settings_path = make_path(data_container.app_name, 'lib', data_container.app_name, 'settings.py')
command_dir = make_path(data_container.app_name, 'lib', data_container.app_name, 'commands')
setuppy_path = make_path(data_container.app_name, 'setup.py')
print(" ")
print(data_container.app_name + " was successfully built.")
print(" ")
print("-----")
print("Main application script: " + main_script_path)
print("Settings file: " + settings_path)
print("Commands directory: " + command_dir)
print("setup.py file: " + setuppy_path)
print("-----")
print(" ")
print("Use 'python setup.py develop' from the top level of your project and you can begin testing your application with the executable, " + data_container.app_name)
exit_success()
#------------------------------------------------------------------------------
# [ InfoCompiler class ]
# obtain information from user in order to build a new project
#------------------------------------------------------------------------------
class InfoCompiler:
def __init__(self, app_name):
self.data = DataContainer()
self.data.app_name = app_name
self.displayed_info_flag = 0
def getUserInfo(self):
if not self.displayed_info_flag:
print("We need some information to create your project.")
self.displayed_info_flag = 1
# If no project name, then query for it because this is mandatory
if self.data.app_name == None:
if python.is_py2:
response = raw_input("Please enter your application name (q=quit): ")
else:
response = input("Please enter your application name (q=quit): ")
if len(response) > 0:
if response == "q":
print("Aborted project build.")
sys.exit(0) # user requested quit
else:
if len(response.split()) > 1: # if more than one word
print("The application name must be a single word. Please try again.")
self.getUserInfo()
else:
self.data.app_name = response
else:
print("The Naked project will not build without an application name. Please try again.")
return self.getUserInfo()
# if project name already set, then obtain the other optional information
if python.is_py2():
self.data.developer = raw_input("Enter the licensing developer or organization (q=quit): ")
if self.data.developer == "q":
print("Aborted the project build.")
sys.exit(0)
self.data.license = raw_input("Enter the license type (or leave blank, q=quit): ")
if self.data.license == "q":
print("Aborted the project build.")
sys.exit(0)
else:
self.data.developer = input("Enter the licensing developer or organization: ")
if self.data.developer == "q":
print("Aborted the project build.")
sys.exit(0)
self.data.license = input("Enter the license type (or leave blank): ")
if self.data.license == "q":
print("Aborted the project build.")
sys.exit(0)
if self.confirmData():
return self.data
else:
print("Let's try again...")
return self.getUserInfo() # try again
def getSetupFileInfo(self):
files = system.list_all_files_cwd()
if len(files) > 0:
setupfile_exists = False
for a_file in files:
if 'naked.yaml' == a_file.lower(): # accepts any permutation of upper/lower case 'naked.yaml'
print("Detected a Naked project YAML setup file (" + a_file + ").")
setupfile_exists = True
fr = nfile.FileReader(a_file)
the_yaml = fr.read_utf8()
self.parseYaml(the_yaml)
if setupfile_exists:
if self.confirmData():
return self.data
else:
print("Aborted the project build.")
if python.is_py2():
response = raw_input("Would you like to modify this information? (y/n) ")
else:
response = input("Would you like to modify this information? (y/n) ")
if response in ['y', 'Y', 'Yes', 'YES', 'yes']:
self.displayed_info_flag = 1
self.data.app_name = None
return self.getUserInfo() # return the result from the getUserInfo command to the calling method
else:
sys.exit(0)
else:
return self.getUserInfo() # there are files but no setup file, use the manual entry method
else:
return self.getUserInfo() # there are no files in the directory, use the manual entry method
def parseYaml(self, yaml_string):
import yaml
the_yaml = yaml.load(yaml_string)
# Parse project name
if 'application' in the_yaml:
self.data.app_name = the_yaml['application']
else:
print("Unable to find the application name ('application' field) in naked.yaml")
if python.is_py2:
response = raw_input("Please enter your application name: ")
else:
response = input("Please enter your application name: ")
if len(response) > 0:
self.data.app_name = response # assign the application name at CL if was not entered in file
else:
print("The Naked project will not build without an application name. Please try again.")
self.displayed_info_flag = 1
self.getUserInfo()
# Parse developer
if 'developer' in the_yaml:
self.data.developer = the_yaml['developer'] # set developer
else:
self.data.developer = ""
# Parse license type
if 'license' in the_yaml:
self.data.license = the_yaml['license'] # set license
else:
self.data.license = ""
def confirmData(self):
templ_str = getHeaderTemplate()
template = ink.Template(templ_str)
renderer = ink.Renderer(template, {'app_name': self.data.app_name, 'developer': self.data.developer, 'license': self.data.license, 'year': self.data.year})
display_header = renderer.render()
print("\nPlease confirm the information below:")
print(display_header)
if python.is_py2():
response = raw_input("Is this correct? (y/n) ")
else:
response = input("Is this correct? (y/n) ")
if response in ['y', 'Y', 'yes', 'YES']:
return True
else:
self.data.app_name = None
return False
#------------------------------------------------------------------------------
# [ getHeaderTemplate function ] (string)
# returns the Ink header template for user confirmation
#------------------------------------------------------------------------------
def getHeaderTemplate():
templ_str = """
----------------------------------------------------------
{{app_name}}
Copyright {{year}} {{developer}}
{{license}}
----------------------------------------------------------
"""
return templ_str
#------------------------------------------------------------------------------
# [ DataContainer class ]
# state maintenance object that holds project information
#------------------------------------------------------------------------------
class DataContainer:
def __init__(self):
self.cwd = system.cwd()
self.year = str(datetime.datetime.now().year)
#------------------------------------------------------------------------------
# [ DirectoryBuilder class ]
# generation of directory structure for a new project
#------------------------------------------------------------------------------
class DirectoryBuilder:
def __init__(self, data_container):
self.data_container = data_container
def build(self):
top_level_dir = self.data_container.app_name
second_level_dirs = ['docs', 'lib', 'tests']
lib_subdir = make_path(self.data_container.app_name, 'commands')
for xdir in second_level_dirs:
make_dirs(make_path(top_level_dir, xdir))
make_dirs(make_path(top_level_dir, 'lib', lib_subdir))
#------------------------------------------------------------------------------
# [ FileBuilder class ]
# generate the files for a new project
#------------------------------------------------------------------------------
class FileBuilder:
def __init__(self, data_container):
self.data_container = data_container
self.file_dictionary = {}
def build_and_write(self):
self._make_file_paths() # create the file paths for all generated files
self._render_file_strings() # create the rendered template strings
self._make_file_dictionary() # make the file path : file string dictionary
self.write_files() # write out to files
return True # if made it this far without exception, return True to calling method to confirm file writes
# files are included in self.file_dictionary as key = filepath, value = filestring pairs
# write the files to disk
def write_files(self):
the_file_xdict = XDict(self.file_dictionary)
for filepath, file_string in the_file_xdict.xitems():
fw = nfile.FileWriter(filepath)
try:
fw.write_utf8(file_string)
except TypeError as te: # catch unicode write errors
fw.write(file_string)
def _make_file_paths(self):
from Naked.toolshed.system import make_path
self.top_manifestin = make_path(self.data_container.app_name, 'MANIFEST.in')
self.top_readmemd = make_path(self.data_container.app_name, 'README.md')
self.top_setupcfg = make_path(self.data_container.app_name, 'setup.cfg')
self.top_setuppy = make_path(self.data_container.app_name, 'setup.py')
self.docs_license = make_path(self.data_container.app_name, 'docs', 'LICENSE')
self.docs_readmerst = make_path(self.data_container.app_name, 'docs', 'README.rst')
self.lib_initpy = make_path(self.data_container.app_name, 'lib', '__init__.py')
self.com_initpy = make_path(self.data_container.app_name, 'lib', self.data_container.app_name, 'commands', '__init__.py')
self.tests_initpy = make_path(self.data_container.app_name, 'tests', '__init__.py')
self.lib_profilerpy = make_path(self.data_container.app_name, 'lib', 'profiler.py')
self.lib_proj_initpy = make_path(self.data_container.app_name, 'lib', self.data_container.app_name, '__init__.py')
self.lib_proj_apppy = make_path(self.data_container.app_name, 'lib', self.data_container.app_name, 'app.py')
self.lib_proj_settingspy = make_path(self.data_container.app_name, 'lib', self.data_container.app_name, 'settings.py')
def _render_file_strings(self):
from Naked.templates.manifest_in_file import manifest_file_string
from Naked.templates.readme_md_file import readme_md_string
from Naked.templates.setup_cfg_file import setup_cfg_string
from Naked.templates.setup_py_file import setup_py_string
from Naked.templates.profiler_file import profiler_file_string
from Naked.templates.app_file import app_file_string
from Naked.templates.settings_file import settings_file_string
data_dict = self.data_container.__dict__
self.top_manifestin_rendered = manifest_file_string # no replacements necessary
self.top_readmemd_rendered = self._render_template(self._create_template(readme_md_string), data_dict) #requires app_name replacement
self.top_setupcfg_rendered = setup_cfg_string # no replacement necessary
self.top_setuppy_rendered = self._render_template(self._create_template(setup_py_string), data_dict) # requires app_name, developer replacements
self.docs_readmerst_rendered = "" # blank document stub write
self.lib_profilerpy_rendered = profiler_file_string # no replacement necessary
self.initpy_rendered = "" # blank __init__.py files
self.lib_proj_apppy_rendered = self._render_template(self._create_template(app_file_string), data_dict) # requires app_name, developer, license_name, year replacements
self.lib_proj_settingspy_rendered = self._render_template(self._create_template(settings_file_string), data_dict) # requires app_name replacement
if len(self.data_container.license) > 0:
license = self.parse_licenses(self.data_container.license) # find the appropriate license template if the license was provided by user
if len(license) > 0: # could be empty string if fails to match a license template provided by Naked
self.docs_license_rendered = self._render_template(self._create_template(license), data_dict)
else:
self.docs_license_rendered = ""
def _make_file_dictionary(self):
file_dictionary = {}
## File path : file string key/value pairs > make as XString and encode as unicode for unicode file writes
file_dictionary[self.top_manifestin] = XString(self.top_manifestin_rendered).unicode().strip()
file_dictionary[self.top_readmemd] = XString(self.top_readmemd_rendered).unicode().strip()
file_dictionary[self.top_setupcfg] = XString(self.top_setupcfg_rendered).unicode().strip()
file_dictionary[self.top_setuppy] = XString(self.top_setuppy_rendered).unicode().strip()
file_dictionary[self.docs_license] = XString(self.docs_license_rendered).unicode().strip()
file_dictionary[self.docs_readmerst] = XString(self.docs_readmerst_rendered).unicode().strip()
file_dictionary[self.lib_initpy] = XString(self.initpy_rendered).unicode().strip()
file_dictionary[self.com_initpy] = XString(self.initpy_rendered).unicode().strip()
file_dictionary[self.tests_initpy] = XString(self.initpy_rendered).unicode().strip()
file_dictionary[self.lib_profilerpy] = XString(self.lib_profilerpy_rendered).unicode().strip()
file_dictionary[self.lib_proj_initpy] = XString(self.initpy_rendered).unicode().strip()
file_dictionary[self.lib_proj_apppy] = XString(self.lib_proj_apppy_rendered).unicode().strip()
file_dictionary[self.lib_proj_settingspy] = XString(self.lib_proj_settingspy_rendered).unicode().strip()
self.file_dictionary = file_dictionary
def _create_template(self, template_string):
return ink.Template(template_string)
def _render_template(self, template, key_dict):
r = ink.Renderer(template, key_dict)
return r.render()
def parse_licenses(self, license_string):
if len(license_string) > 0:
license = license_string.lower() # case insensitive matching, make lower case version
if license.startswith('apache'):
from Naked.templates.licenses import apache_license
return apache_license
elif license.startswith('bsd'):
from Naked.templates.licenses import bsd_license
return bsd_license
elif license.startswith('gpl'):
from Naked.templates.licenses import gpl3_license
return gpl3_license
elif license.startswith('lgpl'):
from Naked.templates.licenses import lgpl_license
return lgpl_license
elif license.startswith('mit'):
from Naked.templates.licenses import mit_license
return mit_license
elif license.startswith('mozilla'):
from Naked.templates.licenses import mozilla_license
return mozilla_license
else:
return ""
def help():
from Naked.toolshed.system import exit_success
help_string = """
Naked make Command Help
=======================
The make command builds a new Naked project. The project can be built from either responses that you give on the command line, or from a naked.yaml project settings file.
USAGE
naked make [argument]
The command should be run in the top level of the path where you would like to create your project. The argument to the make command is optional. If used, this is the name of your new project. It is not necessary to include the argument if you use a naked.yaml project settings file.
The naked.yaml settings file has the following structure:
application: <your project name>
developer: <developer name>
license: <license type>
Place this in the top level of an empty directory and use `naked make` in the same directory. Naked will confirm your settings and then build the project directories and files from these settings.
SECONDARY COMMANDS
none
OPTIONS
none
EXAMPLES
naked make
naked make testapp"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,56 @@
#!/usr/bin/env python
# encoding: utf-8
import os
from Naked.toolshed.system import file_exists, dir_exists, stderr, exit_success
class Profiler:
def __init__(self, dir_levels = 6):
self.number_of_dir_levels = dir_levels # number of directory levels to bottom to top search
def run(self):
lib_found = False
for i in range(self.number_of_dir_levels):
if not self._is_lib_at_this_level():
os.chdir(os.pardir)
else:
lib_found = True
break
if lib_found:
os.chdir('lib') # chdir to the lib directory if it is found
if file_exists('profiler.py'): # confirm that profiler.py exists
os.system('python profiler.py') # run the profiler.py file
exit_success()
else:
stderr("Unable to locate a profiler.py file in your lib directory.", 1)
else:
stderr("Unable to locate your profiler.py file. Please navigate to your project directory.", 1)
def _is_lib_at_this_level(self):
if dir_exists('lib'):
return True
else:
return False
def help():
from Naked.toolshed.system import exit_success
help_string = """
Naked profile Command Help
==========================
The profile command runs cProfile and pstats on the code that you enter in test code block of your PROJECT/lib/profiler.py file.
USAGE
naked profile
SECONDARY COMMANDS
none
OPTIONS
none
This command searches bottom to top (from the working directory) through up to 6 directory levels to identify the lib/profiler.py path."""
print(help_string)
exit_success()

@ -0,0 +1,48 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
def python_help(help_string):
try:
needle = help_string
if needle.startswith("'") and needle.endswith("'"):
needle = needle[1:-1]
elif needle.startswith('"') and needle.endswith('"'):
needle = needle[1:-1]
help(needle)
except Exception as e:
print(e)
sys.stderr.write("•naked• There was an error processing the query.")
sys.exit(1)
def pyh_help():
from Naked.toolshed.system import exit_success
help_string = """
Naked pyh Command Help
======================
The pyh command searches the built-in Python documentation for a query term. The query term can be a Python built-in module, class/type, method, or function.
USAGE
naked pyh <query>
SECONDARY COMMANDS
none
OPTIONS
none
EXAMPLES
Module Docs: naked pyh sys
Class Docs: naked pyh dict
Method Docs: naked pyh dict.update
Function Docs: naked pyh max"""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,204 @@
#!/usr/bin/env python
# encoding: utf-8
import os
from Naked.toolshed.system import cwd, file_exists, dir_exists, stderr, exit_success
#------------------------------------------------------------------------------
# [ ToxTester class ]
# Run Tox on the project directory, by default runs all python versions in tox.ini
# Optional specify the version of Python to test in constructor (runs 'tox -e py<version>')
# Optional specify the number of directory levels `dir_levels` to search bottom to top (default = 4)
#------------------------------------------------------------------------------
class ToxTester:
def __init__(self, py_version="", dir_levels = 6):
self.py_version = py_version
self.number_of_dir_levels = dir_levels
def run(self):
tox_found = False
for i in range(self.number_of_dir_levels):
if not self._is_tox_ini_at_this_level():
os.chdir(os.pardir)
else:
tox_found = True
self._run_tox()
break
if not tox_found:
stderr("Unable to locate your tox.ini file. Please navigate to your project directory.", 1)
else:
exit_success()
def _is_tox_ini_at_this_level(self):
if file_exists('tox.ini'):
return True
else:
return False
def _run_tox(self):
if self.py_version == "":
os.system("tox")
else:
cmd_string = "tox -e" + self.py_version
os.system(cmd_string)
#------------------------------------------------------------------------------
# [ NoseTester class ]
# run nose tests from the tests directory (works from any level of the project)
# Optional specify the number of directory levels to search bottom to top (default = 4)
#------------------------------------------------------------------------------
class NoseTester:
def __init__(self, dir_levels = 6):
self.number_of_dir_levels = dir_levels
def run(self):
nose_found = False
for i in range(self.number_of_dir_levels):
if not self._is_testdir_at_this_level():
os.chdir(os.pardir)
else:
nose_found = True
self._run_nose()
break
if not nose_found:
stderr("Unable to locate your testing directory", 1)
else:
exit_success()
def _is_testdir_at_this_level(self):
if file_exists('setup.py'):
if dir_exists('tests'):
return True
else:
return False #found setup.py but no tests directory
else:
return False # setup.py not at this level
def _run_nose(self):
os.system("nosetests --where=tests")
#------------------------------------------------------------------------------
# [ PyTester class ]
# run py.test test runner in the tests directory
# Optional specify the number of directory levels to search bottom to top (default = 4)
#------------------------------------------------------------------------------
class PyTester:
def __init__(self, dir_levels = 6):
self.number_of_dir_levels = dir_levels
def run(self):
py_found = False
for i in range(self.number_of_dir_levels):
if not self._is_testdir_at_this_level():
os.chdir(os.pardir)
else:
py_found = True
self._run_pytests()
break
if not py_found:
stderr("Unable to locate your testing directory", 1)
else:
exit_success()
def _is_testdir_at_this_level(self):
if file_exists('setup.py'):
if dir_exists('tests'):
return True
else:
return False
else:
return False
def _run_pytests(self):
os.chdir('tests')
os.system('py.test')
#------------------------------------------------------------------------------
# [ UnitTester class ]
# run Python unit tests with the built in unittest methods
# Optional specify the number of directory levels to search bottom to top (default = 4)
#------------------------------------------------------------------------------
class UnitTester:
def __init__(self, the_unit_test, dir_levels = 6):
self.unittest = the_unit_test
self.number_of_dir_levels = dir_levels
def run(self):
unit_found = False
for i in range(self.number_of_dir_levels):
if not self._is_testdir_at_this_level():
os.chdir(os.pardir)
else:
unit_found = True
os.chdir('tests')
if file_exists(self.unittest):
self._run_unittest()
else:
stderr("The unit test file " + self.unittest + " could not be found in the tests directory.")
if not unit_found:
stderr("Unable to locate your testing directory", 1)
else:
exit_success()
def _is_testdir_at_this_level(self):
if file_exists('setup.py'):
if dir_exists('tests'):
return True
else:
return False
else:
return False
def _run_unittest(self):
cmd_string = "python " + self.unittest
os.system(cmd_string)
def help():
help_string = """
Naked test Command Help
=======================
The test command allows you to run unit tests from any working directory in your project.
USAGE
naked test <secondary command> [argument]
SECONDARY COMMANDS
nose - run the nose test runner on your project
pytest - run the py.test test runner on your project
tox - run the tox test runner on your project
unittest - run Python unit tests (built-in)
ARGUMENTS
nose
-- does not take additional arguments
pytest
-- does not take additional arguments
tox [python version]
-- You can include an optional tox Python version argument to run your
tests with a single version of Python (instead of the versions
specified in the tox.ini file). By default, the versions specified
in your tox.ini file are run.
unittest <test file>
-- Mandatory unit test file path (relative to the tests directory)
OPTIONS
none
EXAMPLES
naked test nose
naked test pytest
naked test tox
naked test tox py27
naked test unittest test_app.py
A bottom to top search (from the working directory) is performed over up to 6 directory levels to find the 'tests' directory."""
print(help_string)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,17 @@
#!/usr/bin/env python
# encoding: utf-8
import Naked.settings
from Naked.toolshed.system import exit_success
class Usage:
def __init__(self):
self.usage = Naked.settings.usage
def print_usage(self):
print(self.usage)
exit_success()
if __name__ == '__main__':
pass

@ -0,0 +1,25 @@
#!/usr/bin/env python
# encoding: utf-8
import Naked.settings
from Naked.toolshed.system import exit_success
class Version:
def __init__(self):
self.major_version = Naked.settings.major_version
self.minor_version = Naked.settings.minor_version
self.patch_version = Naked.settings.patch_version
self.name = Naked.settings.app_name
self.app_version_string = self.name + " " + self.major_version + "." + self.minor_version + "." + self.patch_version
self.version_string = self.major_version + "." + self.minor_version + "." + self.patch_version
def print_version(self):
print(self.app_version_string)
exit_success()
def get_version(self):
return self.version_string
if __name__ == '__main__':
pass

@ -0,0 +1,28 @@
#!/usr/bin/env python
# encoding: utf-8
# import sys
# from functools import wraps
# from Naked.toolshed.types import XMaxHeap, XMinHeap
# def print_scratch(func):
# @wraps(func)
# def print_wrapper(*args, **kwargs):
# print(func(*args, **kwargs))
# return print_wrapper
# def run_scratchpad():
# # from Naked.toolshed.file import FileReader
# # from Naked.toolshed.types import XString, XUnicode
# # r = FileReader('/Users/ces/Desktop/code/naked/tests/testfiles/unicode.txt')
# # test1 = r.read_utf8()
# # test2 = XUnicode(test1, {'a': 'b'})
# # test3 = "Hey! It's Bengali ব য,and here is some more ২"
# # print(unicode(test2))
# if __name__ == '__main__':
# run_scratchpad()

@ -0,0 +1,86 @@
#!/usr/bin/env python
# encoding: utf-8
#------------------------------------------------------------------------------
# Application Name
#------------------------------------------------------------------------------
app_name = "naked"
#------------------------------------------------------------------------------
# Version Number
#------------------------------------------------------------------------------
major_version = "0"
minor_version = "1"
patch_version = "31"
#------------------------------------------------------------------------------
# Debug Flag (switch to False for production release code)
#------------------------------------------------------------------------------
debug = False
#------------------------------------------------------------------------------
# Usage String
#------------------------------------------------------------------------------
usage = """
Usage: naked <primary command> [secondary command] [option(s)] [argument(s)]
--- Use 'naked help' for detailed help ---
"""
#------------------------------------------------------------------------------
# Help String
#------------------------------------------------------------------------------
help = """
---------------------------------------------------
Naked
A Python command line application framework
Copyright 2014 Christopher Simpkins
MIT license
---------------------------------------------------
ABOUT
The Naked framework includes the "naked" executable and the Python toolshed library. The naked executable is a command line tool for application development, testing, profiling, and deployment. The toolshed library contains numerous useful tools for application development that can be used through standard Python module imports. These features are detailed in the documentation (link below).
USAGE
The naked executable syntax is:
naked <primary command> [secondary command] [option(s)] [argument(s)]
The <primary command> is mandatory and includes one of the commands in the following section. The [bracketed] syntax structure is optional and dependent upon the primary command that you use. Use the command 'naked <primary command> help' for details about a command.
PRIMARY COMMANDS SECONDARY COMMANDS
args help
build help
classify help
dist allhelpsdistswheelwheelwin
help - none -
locate mainhelpsettingssetup
make help
profile help
pyh help
test nosepytesttoxunittest
usage - none -
version - none -
HELP
To learn more about a primary command, use the following syntax:
naked <primary command> help
DOCUMENTATION
http://docs.naked-py.com
SOURCE REPOSITORY
https://github.com/chrissimpkins/naked
ISSUE REPORTING
https://github.com/chrissimpkins/naked/issues
"""

@ -0,0 +1,101 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS = app_name, developer, license_name, year
app_file_string = """
#!/usr/bin/env python
# encoding: utf-8
#------------------------------------------------------------------------------
# {{app_name}}
# Copyright {{year}} {{developer}}
# {{license}}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------------
# c.cmd = Primary command ({{app_name}} <primary command>)
# c.cmd2 = Secondary command ({{app_name}} <primary command> <secondary command>)
#
# c.arg_to_cmd = first positional argument to the primary command
# c.arg_to_cmd2 = first positional argument to the secondary command
#
# c.option(option_string, [bool argument_required]) = test for option with optional positional argument to option test
# c.option_with_arg(option_string) = test for option and mandatory positional argument to option
# c.flag(flag_string) = test for presence of a "option=argument" style flag
#
# c.arg(arg_string) = returns the next positional argument to the arg_string argument
# c.flag_arg(flag_string) = returns the flag assignment for a "--option=argument" style flag
#------------------------------------------------------------------------------------
# Application start
def main():
import sys
from Naked.commandline import Command
from Naked.toolshed.state import StateObject
#------------------------------------------------------------------------------------------
# [ Instantiate command line object ]
# used for all subsequent conditional logic in the CLI application
#------------------------------------------------------------------------------------------
c = Command(sys.argv[0], sys.argv[1:])
#------------------------------------------------------------------------------
# [ Instantiate state object ]
#------------------------------------------------------------------------------
state = StateObject()
#------------------------------------------------------------------------------------------
# [ Command Suite Validation ] - early validation of appropriate command syntax
# Test that user entered at least one argument to the executable, print usage if not
#------------------------------------------------------------------------------------------
if not c.command_suite_validates():
from {{app_name}}.settings import usage as {{app_name}}_usage
print({{app_name}}_usage)
sys.exit(1)
#------------------------------------------------------------------------------------------
# [ NAKED FRAMEWORK COMMANDS ]
# Naked framework provides default help, usage, and version commands for all applications
# --> settings for user messages are assigned in the lib/{{app_name}}/settings.py file
#------------------------------------------------------------------------------------------
if c.help(): # User requested {{app_name}} help information
from {{app_name}}.settings import help as {{app_name}}_help
print({{app_name}}_help)
sys.exit(0)
elif c.usage(): # User requested {{app_name}} usage information
from {{app_name}}.settings import usage as {{app_name}}_usage
print({{app_name}}_usage)
sys.exit(0)
elif c.version(): # User requested {{app_name}} version information
from {{app_name}}.settings import app_name, major_version, minor_version, patch_version
version_display_string = app_name + ' ' + major_version + '.' + minor_version + '.' + patch_version
print(version_display_string)
sys.exit(0)
#------------------------------------------------------------------------------------------
# [ PRIMARY COMMAND LOGIC ]
# Enter your command line parsing logic below
#------------------------------------------------------------------------------------------
# [[ Example usage ]] ------------------------------->>>
# if c.cmd == 'hello':
# if c.cmd2 = 'world':
# if c.option('--print'):
# print('Hello World!')
# elif c.cmd == 'spam':
# if c.option_with_arg('--with'):
# friend_of_spam = c.arg('--with') # user enters {{app_name}} spam --with eggs
# print('spam and ' + friend_of_spam) # prints 'spam and eggs'
# elif c.cmd == 'naked':
# if c.flag("--language"):
# lang = c.flag_arg("--language") # user enters {{app_name}} naked --language=python
# print("Naked & " + lang) # prints 'Naked & python'
# End example --------------------------------------->>>
#------------------------------------------------------------------------------------------
# [ DEFAULT MESSAGE FOR MATCH FAILURE ]
# Message to provide to the user when all above conditional logic fails to meet a true condition
#------------------------------------------------------------------------------------------
else:
print("Could not complete the command that you entered. Please try again.")
sys.exit(1) #exit
if __name__ == '__main__':
main()
"""

@ -0,0 +1,140 @@
#!/usr/bin/env python
# encoding: utf-8
# ALL LICENSES: VARS = year, developer
#------------------------------------------------------------------------------
# [ apache_license ]
# The Apache License
#------------------------------------------------------------------------------
apache_license = """
Copyright {{year}} {{developer}}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
#------------------------------------------------------------------------------
# [ bsd_license ]
# The BSD 2-clause license
#------------------------------------------------------------------------------
bsd_license = """
Copyright (c) {{year}}, {{developer}}
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
#------------------------------------------------------------------------------
# [ gpl3_license ]
# The GPL v3 License
#------------------------------------------------------------------------------
gpl3_license = """
Copyright (C) {{year}} {{developer}}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see [http://www.gnu.org/licenses/].
"""
#------------------------------------------------------------------------------
# [lgpl_license ]
# The Lesser GPL license
#------------------------------------------------------------------------------
lgpl_license = """
Copyright (C) {{year}} {{developer}}
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
"""
#------------------------------------------------------------------------------
# [ mit_license ]
# The MIT License
#------------------------------------------------------------------------------
mit_license = """
The MIT License (MIT)
Copyright (c) {{year}} {{developer}}
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
#------------------------------------------------------------------------------
# [ mozilla_license ]
# The Mozilla Public license, v2.0
#------------------------------------------------------------------------------
mozilla_license = """
Mozilla Public License, v.2.0
Copyright (c) {{year}} {{developer}}
This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""

@ -0,0 +1,5 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS = --none--
manifest_file_string = "recursive-include docs *"

@ -0,0 +1,45 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS = --none--
profiler_file_string = """
#!/usr/bin/env python
# encoding: utf-8
import cProfile, pstats, StringIO
def profile():
#------------------------------------------------------------------------------
# Setup a profile
#------------------------------------------------------------------------------
pr = cProfile.Profile()
#------------------------------------------------------------------------------
# Enter setup code below
#------------------------------------------------------------------------------
# Optional: include setup code here
#------------------------------------------------------------------------------
# Start profiler
#------------------------------------------------------------------------------
pr.enable()
#------------------------------------------------------------------------------
# BEGIN profiled code block
#------------------------------------------------------------------------------
# include profiled code here
#------------------------------------------------------------------------------
# END profiled code block
#------------------------------------------------------------------------------
pr.disable()
s = StringIO.StringIO()
sortby = 'cumulative'
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.strip_dirs().sort_stats("time").print_stats()
print(s.getvalue())
if __name__ == '__main__':
profile()
"""

@ -0,0 +1,32 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS = year
pypush_file_string = """
#!/bin/sh
# Scriptacular - pypush.sh
# Create a Python source distribution and push it to PyPI
# Copyright {{year}} Christopher Simpkins
# MIT License
# Build and push to PyPI
python setup.py sdist upload
# Confirm that it worked
if (( $? )); then
echo "Unable to distribute your release to PyPI" >&2
exit 1
fi
python setup.py bdist_wheel upload
# Confirm that wheel distribution worked
if (( $? )); then
echo "Unable to distribute your wheel to PyPI" >&2
exit 1
fi
# Exit success
exit 0
"""

@ -0,0 +1,8 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS: app_name
readme_md_string = """
{{app_name}}
=====
"""

@ -0,0 +1,35 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS = app_name
settings_file_string = """
#!/usr/bin/env python
# encoding: utf-8
#------------------------------------------------------------------------------
# Application Name
#------------------------------------------------------------------------------
app_name = '{{app_name}}'
#------------------------------------------------------------------------------
# Version Number
#------------------------------------------------------------------------------
major_version = "0"
minor_version = "1"
patch_version = "0"
#------------------------------------------------------------------------------
# Debug Flag (switch to False for production release code)
#------------------------------------------------------------------------------
debug = True
#------------------------------------------------------------------------------
# Usage String
#------------------------------------------------------------------------------
usage = ''
#------------------------------------------------------------------------------
# Help String
#------------------------------------------------------------------------------
help = ''
"""

@ -0,0 +1,8 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS: --none--
setup_cfg_string = """
[wheel]
universal = 1
"""

@ -0,0 +1,56 @@
#!/usr/bin/env python
# encoding: utf-8
# VARS: app_name, developer, license
setup_py_string = ("""
import os
import re
from setuptools import setup, find_packages
def docs_read(fname):
return open(os.path.join(os.path.dirname(__file__), 'docs', fname)).read()
def version_read():
settings_file = open(os.path.join(os.path.dirname(__file__), 'lib', '{{app_name}}', 'settings.py')).read()
major_regex = """ + '"""' + """major_version\s*?=\s*?["']{1}(\d+)["']{1}""" + '"""' + '\n ' +
'minor_regex = ' + '"""' + """minor_version\s*?=\s*?["']{1}(\d+)["']{1}""" + '"""' + '\n ' +
'patch_regex = ' + '"""' + """patch_version\s*?=\s*?["']{1}(\d+)["']{1}""" + '"""' + '\n ' +
"""major_match = re.search(major_regex, settings_file)
minor_match = re.search(minor_regex, settings_file)
patch_match = re.search(patch_regex, settings_file)
major_version = major_match.group(1)
minor_version = minor_match.group(1)
patch_version = patch_match.group(1)
if len(major_version) == 0:
major_version = 0
if len(minor_version) == 0:
minor_version = 0
if len(patch_version) == 0:
patch_version = 0
return major_version + "." + minor_version + "." + patch_version
setup(
name='{{app_name}}',
version=version_read(),
description='',
long_description=(docs_read('README.rst')),
url='',
license='{{license}}',
author='{{developer}}',
author_email='',
platforms=['any'],
entry_points = {
'console_scripts': [
'{{app_name}} = {{app_name}}.app:main'
],
},
packages=find_packages("lib"),
package_dir={'': 'lib'},
install_requires=['Naked'],
keywords='',
include_package_data=True,
classifiers=[],
)
""")

@ -0,0 +1,463 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
import time
import gc
from functools import wraps
#------------------------------------------------------------------------------
# [ timer function decorator ]
# runs timed repetitions of the decorated function in a single trial
# default is 100,000 repetitions in the trial
# reports the results of the trial
# Usage example:
# from Naked.toolshed.benchmarking import timer
# @timer
# def myfunction():
#------------------------------------------------------------------------------
def timer(func, repetitions=100000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
#------------------------------------------------------------------------------
# [ timer_X function decorators ]
# replicate the above decorator with different number of repetitions
#------------------------------------------------------------------------------
def timer_10(func, repetitions=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_100(func, repetitions=100):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_1k(func, repetitions=1000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_10k(func, repetitions=10000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_1m(func, repetitions=1000000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
#------------------------------------------------------------------------------
# [ timer_trials_benchmark decorator function ]
# time a function and compare to a benchmark function
# default is 10 trials x 100,000 repetitions/trial for each function
# Results:
# - Mean of the 10 trials of the test function
# - standard deviation of the 10 trials (if numpy is available)
# - result for 100,000 repetitions of the benchmark function
# - ratio of the test : benchmark function results
# Usage example:
# from Naked.toolshed.benchmarking import timer_trials_benchmark
# @timer_trials_benchmark
# def myfunction():
#------------------------------------------------------------------------------
def timer_trials_benchmark(func, repetitions=100000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
#------------------------------------------------------------------------------
# [ timer_trials_benchmark_X decorators ]
# additional benchmark decorators that replicate the above function with different # repetitions
#------------------------------------------------------------------------------
def timer_trials_benchmark_10(func, repetitions=10, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_100(func, repetitions=100, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_1k(func, repetitions=1000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_10k(func, repetitions=10000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_1m(func, repetitions=1000000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
if __name__ == '__main__':
pass

@ -0,0 +1,463 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
import time
import gc
from functools import wraps
#------------------------------------------------------------------------------
# [ timer function decorator ]
# runs timed repetitions of the decorated function in a single trial
# default is 100,000 repetitions in the trial
# reports the results of the trial
# Usage example:
# from Naked.toolshed.benchmarking import timer
# @timer
# def myfunction():
#------------------------------------------------------------------------------
def timer(func, repetitions=100000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
#------------------------------------------------------------------------------
# [ timer_X function decorators ]
# replicate the above decorator with different number of repetitions
#------------------------------------------------------------------------------
def timer_10(func, repetitions=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_100(func, repetitions=100):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_1k(func, repetitions=1000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_10k(func, repetitions=10000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
def timer_1m(func, repetitions=1000000):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting " + str(repetitions) + " repetitions of " + func.__name__ + "()...")
sys.stdout.flush()
print(" ")
# disable garbage collection
gc.collect()
gc.disable()
start = time.time()
for x in range(repetitions):
result = func(*args, **kwargs)
end = time.time()
gc.enable() # re-enable garbage collection
gc.collect()
print(str(repetitions) + " repetitions of " + func.__name__ + " : " + str(end-start) + " sec")
return result
return wrapper
#------------------------------------------------------------------------------
# [ timer_trials_benchmark decorator function ]
# time a function and compare to a benchmark function
# default is 10 trials x 100,000 repetitions/trial for each function
# Results:
# - Mean of the 10 trials of the test function
# - standard deviation of the 10 trials (if numpy is available)
# - result for 100,000 repetitions of the benchmark function
# - ratio of the test : benchmark function results
# Usage example:
# from Naked.toolshed.benchmarking import timer_trials_benchmark
# @timer_trials_benchmark
# def myfunction():
#------------------------------------------------------------------------------
def timer_trials_benchmark(func, repetitions=100000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
#------------------------------------------------------------------------------
# [ timer_trials_benchmark_X decorators ]
# additional benchmark decorators that replicate the above function with different # repetitions
#------------------------------------------------------------------------------
def timer_trials_benchmark_10(func, repetitions=10, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_100(func, repetitions=100, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_1k(func, repetitions=1000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_10k(func, repetitions=10000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
def timer_trials_benchmark_1m(func, repetitions=1000000, trials=10):
@wraps(func)
def wrapper(*args, **kwargs):
sys.stdout.write("Starting timed trials of " + func.__name__ + "()")
sys.stdout.flush()
result_list = []
benchmark_list = []
# disable garbage collection
gc.collect()
gc.disable()
for x in range(trials):
# test function
start = time.time()
for y in range(repetitions):
func(*args, **kwargs)
end = time.time()
result = func(*args, **kwargs)
result_list.append(end-start)
# benchmark function
L = []
start2 = time.time()
for j in range(repetitions):
for i in range(10):
L.append(i)
end2 = time.time()
benchmark_list.append(end2 - start2)
sys.stdout.write(".")
sys.stdout.flush()
gc.enable() # re-enable garbage collection
gc.collect()
print(" ")
n = 1
for run in result_list:
print("Trial " + str(n) + ":\t" + str(run))
n += 1
print("-"*50)
mean = sum(result_list)/len(result_list)
mean_benchmark = sum(benchmark_list)/len(benchmark_list)
print("Mean for " + str(repetitions) + " repetitions: " + str(mean) + " sec")
try:
import numpy as np
array = np.array(result_list)
print( "Standard Deviation: " + str(np.std(array)))
except ImportError as ie:
pass
print("Mean per repetition: " + str(mean/repetitions) + " sec")
print("Mean for " + str(repetitions) + " of benchmark function:" + str(mean_benchmark) + " sec")
print("Ratio: " + str(mean/mean_benchmark))
return result
return wrapper
if __name__ == '__main__':
pass

@ -0,0 +1,117 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=True
cdef inline int increment(object iterable, object test_string):
cdef int count = 0
cdef object thing
for thing in iterable:
if thing == test_string:
count += 1
return count
from Naked.toolshed.c.types import NakedObject, XFSet, XDict, XList, XQueue, XSet, XString
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [ nob ] (NakedObject)
# Cast a dictionary of attributes to a NakedObject with key>attribute mapping
#------------------------------------------------------------------------------
def nob(attributes={}):
try:
return NakedObject(attributes)
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to create a NakedObject with the requested argument using the nobj() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xd function ] (XDict)
# Cast a Python dictionary to a XDict
#------------------------------------------------------------------------------
def xd(dictionary_arg, attributes={}):
try:
return XDict(dictionary_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XDict with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XDict with the xd() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xl function ] (XList)
# Cast a Python list, set, or tuple to a XList
#------------------------------------------------------------------------------
def xl(list_arg, attributes={}):
try:
return XList(list_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XList with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XList with the xl() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xq function ] (XQueue)
# Cast a Python list, set, tuple to a XQueue
#------------------------------------------------------------------------------
def xq(queue_arg, attributes={}):
try:
return XQueue(queue_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XQueue with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XQueue with the xq() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xset function ] (XSet)
# Cast a Python set to a XSet
#------------------------------------------------------------------------------
def xset(set_arg, attributes={}):
try:
return XSet(set_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XSet with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XSet with the xset() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xfset function ] (XFSet)
# Cast a Python set to a XFSet
#------------------------------------------------------------------------------
def xfset(set_arg, attributes={}):
try:
return XFSet(set_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XSet with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XSet with the xset() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xstr function ] (XString)
# Cast a Python string to a XString
#------------------------------------------------------------------------------
def xstr(string_arg, attributes={}):
try:
return XString(string_arg, attributes)
except TypeError as te:
raise TypeError("Attempted to cast to a XString with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XString with the xstr() function (Naked.toolshed.casts.py).")
raise e
if __name__ == '__main__':
test = xstr("A test", {'arg1': '2'})
print(test)
print(test[0])
print(test.arg1)
print(type(test))

@ -0,0 +1,35 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
from Naked.settings import debug as DEBUG_FLAG
from Naked.toolshed.c.system import cwd
import Naked.toolshed.c.python as py
import sys
import os
import datetime
class StateObject:
def __init__(self):
now = datetime.datetime.now()
self.py2 = py.is_py2() #truth test Python 2 interpreter
self.py3 = py.is_py3() #truth test Python 3 interpreter
self.py_major = py.py_major_version() #Python major version
self.py_minor = py.py_minor_version() #Python minor version
self.py_patch = py.py_patch_version() #Python patch version
self.os = sys.platform #user operating system
self.cwd = cwd() #current (present) working directory
self.parent_dir = os.pardir
self.default_path = os.defpath
self.user_path = os.path.expanduser("~")
self.string_encoding = sys.getdefaultencoding()
self.file_encoding = sys.getfilesystemencoding()
self.hour = now.hour
self.min = now.minute
self.year = now.year
self.day = now.day
self.month = now.month
self.second = now.second
if __name__ == '__main__':
pass

@ -0,0 +1,15 @@
echo "Cythonizing .pyx files to C files"
cython benchmarking.pyx
cython casts.pyx
cython file.pyx
cython ink.pyx
cython network.pyx
cython python.pyx
cython shell.pyx
cython cstate.pyx
cython system.pyx
cython types.pyx
echo "Cythonization is complete"

@ -0,0 +1,377 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
import sys
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [ IO class ]
# interface for all local file IO classes
#------------------------------------------------------------------------------
class IO:
def __init__(self,filepath):
self.filepath = filepath
#------------------------------------------------------------------------------
# [ FileWriter class ]
# writes data to local files
#------------------------------------------------------------------------------
class FileWriter(IO):
def __init__(self, filepath):
IO.__init__(self, filepath)
#------------------------------------------------------------------------------
# [ append method ]
# Universal text file writer that appends to existing file using system default text encoding or utf-8 if throws unicode error
# Tests: test_IO.py:: test_file_ascii_readwrite_append, test_file_append_missingfile
#------------------------------------------------------------------------------
def append(self, text):
try:
from Naked.toolshed.system import file_exists
if not file_exists(self.filepath): #confirm that file exists, if not raise IOError (assuming that developer expected existing file if using append)
raise IOError("The file specified for the text append does not exist (Naked.toolshed.file.py:append).")
with open(self.filepath, 'a') as appender:
appender.write(text)
except UnicodeEncodeError as ue:
self.append_utf8(text) #try writing as utf-8
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to append text to the file with the append() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ append_utf8 method ]
# Text writer that appends text to existing file with utf-8 encoding
# Tests: test_IO.py :: test_file_utf8_readwrite_append
#------------------------------------------------------------------------------
def append_utf8(self, text):
try:
from Naked.toolshed.system import file_exists
if not file_exists(self.filepath):
raise IOError("The file specified for the text append does not exist (Naked.toolshed.file.py:append_utf8).")
import codecs
import unicodedata
norm_text = unicodedata.normalize('NFKD', text) # NKFD normalization of the unicode data before write
with codecs.open(self.filepath, mode='a', encoding="utf_8") as appender:
appender.write(norm_text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to append text to the file with the append_utf8 method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ gzip method (writer) ]
# writes data to gzip compressed file
# Note: adds .gz extension to filename if user did not specify it in the FileWriter class constructor
# Note: uses compresslevel = 6 as default to balance speed and compression level (which in general is not significantly less than 9)
# Tests: test_IO.py :: test_file_gzip_ascii_readwrite, test_file_gzip_utf8_readwrite,
# test_file_gzip_utf8_readwrite_explicit_decode
#------------------------------------------------------------------------------
def gzip(self, text, compression_level=6):
try:
import gzip
if not self.filepath.endswith(".gz"):
self.filepath = self.filepath + ".gz"
with gzip.open(self.filepath, 'wb', compresslevel=compression_level) as gzip_writer:
gzip_writer.write(text)
except UnicodeEncodeError as ue:
import unicodedata
norm_text = unicodedata.normalize('NFKD', text) # NKFD normalization of the unicode data before write
import codecs
binary_data = codecs.encode(norm_text, "utf_8")
with gzip.open(self.filepath, 'wb', compresslevel=compression_level) as gzip_writer:
gzip_writer.write(binary_data)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to gzip compress the file with the gzip method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write method ]
# Universal text file writer that writes by system default or utf-8 encoded unicode if throws UnicdeEncodeError
# Tests: test_IO.py :: test_file_ascii_readwrite, test_file_ascii_readwrite_missing_file,
# test_file_utf8_write_raises_unicodeerror
#------------------------------------------------------------------------------
def write(self, text):
try:
with open(self.filepath, 'wt') as writer:
writer.write(text)
except UnicodeEncodeError as ue:
self.write_utf8(text) # attempt to write with utf-8 encoding
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write to requested file with the write() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write_as method ]
# text file writer that uses developer specified text encoding
# Tests: test_IO.py :: test_file_utf8_readas_writeas
#------------------------------------------------------------------------------
def write_as(self, text, the_encoding=""):
try:
if the_encoding == "": #if the developer did not include the encoding type, raise an exception
raise RuntimeError("The text encoding was not specified as an argument to the write_as() method (Naked.toolshed.file.py:write_as).")
import codecs
with codecs.open(self.filepath, encoding=the_encoding, mode='w') as f:
f.write(text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to write file with the specified encoding using the write_as() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write_bin method ]
# binary data file writer
# Tests: test_IO.py :: test_file_bin_readwrite
#------------------------------------------------------------------------------
def write_bin(self, binary_data):
try:
with open(self.filepath, 'wb') as bin_writer:
bin_writer.write(binary_data)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write binary data to file with the write_bin method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ safe_write method ] (boolean)
# Universal text file writer (writes in default encoding unless throws unicode error) that will NOT overwrite existing file at the requested filepath
# returns boolean indicator for success of write based upon test for existence of file (False = write failed because file exists)
# Tests: test_IO.py :: test_file_ascii_safewrite, test_file_utf8_safewrite
#------------------------------------------------------------------------------
def safe_write(self, text):
import os.path
if not os.path.exists(self.filepath): # if the file does not exist, then can write
try:
with open(self.filepath, 'wt') as writer:
writer.write(text)
return True
except UnicodeEncodeError as ue:
self.write_utf8(text)
return True
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write to requested file with the safe_write() method (Naked.toolshed.file.py).")
raise e
else:
return False # if file exists, do not write and return False
#------------------------------------------------------------------------------
# [ safe_write_bin method ]
# Binary data file writer that will NOT overwrite existing file at the requested filepath
# returns boolean indicator for success of write based upon test for existence of file (False = write failed because file exists)
#------------------------------------------------------------------------------
def safe_write_bin(self, file_data):
try:
import os.path
if not os.path.exists(self.filepath):
with open(self.filepath, 'wb') as writer:
writer.write(file_data)
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write to requested file with the safe_write_bin() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write_utf8 method ]
# Text file writer with explicit UTF-8 text encoding
# uses filepath from class constructor
# requires text to passed as a method parameter
# Tests: test_IO.py :: test_file_utf8_readwrite, test_file_utf8_readwrite_raises_unicodeerror
#------------------------------------------------------------------------------
def write_utf8(self, text):
try:
import codecs
f = codecs.open(self.filepath, encoding='utf_8', mode='w')
except IOError as ioe:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to open file for write with the write_utf8() method (Naked.toolshed.file.py).")
raise ioe
try:
import unicodedata
norm_text = unicodedata.normalize('NFKD', text) # NKFD normalization of the unicode data before write
f.write(norm_text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write UTF-8 encoded text to file with the write_utf8() method (Naked.toolshed.file.py).")
raise e
finally:
f.close()
#------------------------------------------------------------------------------
# [ FileReader class ]
# reads data from local files
# filename assigned in constructor (inherited from IO class interface)
#------------------------------------------------------------------------------
class FileReader(IO):
def __init__(self, filepath):
IO.__init__(self, filepath)
#------------------------------------------------------------------------------
# [ read method ] (string)
# Universal text file reader that will read utf-8 encoded unicode or non-unicode text as utf-8
# returns string or unicode (py3 = string for unicode and non-unicode, py2 = str for non-unicode, unicode for unicode)
# Tests: test_IO.py :: test_file_ascii_readwrite, test_file_read_missing_file,
#------------------------------------------------------------------------------
def read(self):
try:
return self.read_utf8() #reads everything as unicode in utf8 encoding
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read text from the requested file with the read() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ read_bin method ] (binary byte string)
# Universal binary data file reader
# returns file contents in binary mode as binary byte strings
# Tests: test_IO.py :: test_file_bin_readwrite, test_file_read_bin_missing_file
#------------------------------------------------------------------------------
def read_bin(self):
try:
with open(self.filepath, 'rb') as bin_reader:
data = bin_reader.read()
return data
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read the binary data from the file with the read_bin method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ read_as method ] (string with developer specified text encoding)
# Text file reader with developer specified text encoding
# returns file contents in developer specified text encoding
# Tests: test_IO.py :: test_file_utf8_readas_writeas, test_file_readas_missing_file
#------------------------------------------------------------------------------
def read_as(self, the_encoding):
try:
if the_encoding == "":
raise RuntimeError("The text file encoding was not specified as an argument to the read_as method (Naked.toolshed.file.py:read_as).")
import codecs
with codecs.open(self.filepath, encoding=the_encoding, mode='r') as f:
data = f.read()
return data
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read the file with the developer specified text encoding with the read_as method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ readlines method ] (list of strings)
# Read text from file line by line, uses utf8 encoding by default
# returns list of utf8 encoded file lines as strings
# Tests: test_IO.py :: test_file_readlines, test_file_readlines_missing_file
#------------------------------------------------------------------------------
def readlines(self):
try:
return self.readlines_utf8() # read as utf8 encoded file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read text from the requested file with the readlines() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ readlines_as method ] (list of developer specified encoded strings)
# Read lines from file with developer specified text encoding
# Returns a list of developer specified encoded lines from the file
# Tests: test_IO.py ::
#------------------------------------------------------------------------------
def readlines_as(self, dev_spec_encoding):
try:
if dev_spec_encoding == "":
raise RuntimeError("The text file encoding was not specified as an argument to the readlines_as method (Naked.toolshed.file.py:readlines_as).")
import codecs
with codecs.open(self.filepath, encoding=dev_spec_encoding, mode='r') as reader:
data_list = []
for line in reader:
data_list.append(line)
return data_list
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to read lines in the specified encoding with the readlines_as method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ readlines_utf8 method ] (list of utf-8 encoded strings)
# Read text from unicode file by line
# Returns list of file unicode text lines as unicode strings
# Tests: test_IO.py :: test_file_readlines_unicode, test_file_readlines_utf8_missing_file
#------------------------------------------------------------------------------
def readlines_utf8(self):
try:
import codecs
with codecs.open(self.filepath, encoding='utf-8', mode='r') as uni_reader:
modified_text_list = []
for line in uni_reader:
import unicodedata
norm_line = unicodedata.normalize('NFKD', line) # NKFD normalization of the unicode data before use
modified_text_list.append(norm_line)
return modified_text_list
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to read lines in the unicode file with the readlines_utf8 method (Naked.toolshed.file.py)")
raise e
#------------------------------------------------------------------------------
# [ read_gzip ] (byte string)
# reads data from a gzip compressed file
# returns the decompressed binary data from the file
# Note: if decompressing unicode file, set encoding="utf-8"
# Tests: test_IO.py :: test_file_gzip_ascii_readwrite, test_file_gzip_utf8_readwrite,
# test_file_read_gzip_missing_file
#------------------------------------------------------------------------------
def read_gzip(self, encoding="system_default"):
try:
import gzip
with gzip.open(self.filepath, 'rb') as gzip_reader:
file_data = gzip_reader.read()
if encoding in ["utf-8", "utf8", "utf_8", "UTF-8", "UTF8", "UTF_8"]:
import codecs
file_data = codecs.decode(file_data, "utf-8")
import unicodedata
norm_data = unicodedata.normalize('NFKD', file_data) # NKFD normalization of the unicode data before passing back to the caller
return norm_data
else:
return file_data
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read from the gzip compressed file with the read_gzip() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ read_utf8 method ] (string)
# read data from a file with explicit UTF-8 encoding
# uses filepath from class constructor
# returns a unicode string containing the file data (unicode in py2, str in py3)
# Tests: test_IO.py :: test_file_utf8_readwrite, test_file_utf8_readwrite_append,
# test_file_read_utf8_missing_file
#------------------------------------------------------------------------------
def read_utf8(self):
try:
import codecs
f = codecs.open(self.filepath, encoding='utf_8', mode='r')
except IOError as ioe:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to open file for read with read_utf8() method (Naked.toolshed.file.py).")
raise ioe
try:
textstring = f.read()
import unicodedata
norm_text = unicodedata.normalize('NFKD', textstring) # NKFD normalization of the unicode data before returns
return norm_text
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read the file with UTF-8 encoding using the read_utf8() method (Naked.toolshed.file.py).")
raise e
finally:
f.close()
if __name__ == '__main__':
pass

@ -0,0 +1,106 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
#------------------------------------------------------------------------------
# The Ink Templating System
# A lightweight, fast, flexible text templating system
# Copyright 2014 Christopher Simpkins
# MIT License
#------------------------------------------------------------------------------
import re
#------------------------------------------------------------------------------
# Template class
# A template string class that is inherited from Python str
# Includes metadata about the template:
# odel = opening delimiter
# cdel = closing delimiter
# varlist = inclusive list of all variables in the template text (parsed in constructor)
# Delimiters:
# default = {{variable}}
# assign new opening and closing delimiters as parameters when you make a new Template instance
# `escape_regex` boolean is a speedup, avoids Python escape of special regex chars if you do not need it
#------------------------------------------------------------------------------
class Template(str):
def __new__(cls, template_text, open_delimiter="{{", close_delimiter="}}", escape_regex=False):
obj = str.__new__(cls, template_text)
obj.odel = open_delimiter
obj.cdel = close_delimiter
obj.varlist = obj._make_var_list(template_text, escape_regex) #contains all unique parsed variables from the template in a list
return obj
#------------------------------------------------------------------------------
# [ _make_var_list method ] (list of strings)
# Private method that parses the template string for all variables that match the delimiter pattern
# Returns a list of the variable names as strings
#------------------------------------------------------------------------------
def _make_var_list(self, template_text, escape_regex=False):
if escape_regex:
open_match_pat = self._escape_regex_special_chars(self.odel)
close_match_pat = self._escape_regex_special_chars(self.cdel)
match_pat = open_match_pat + r'(.*?)' + close_match_pat # capture group contains the variable name used between the opening and closing delimiters
else:
match_pat = self.odel + r'(.*?)' + self.cdel
var_list = re.findall(match_pat, template_text) #generate a list that contains the capture group from the matches (i.e. the variables in the template)
return set(var_list) # remove duplicate entries by converting to set (and lookup speed improvement from hashing)
#------------------------------------------------------------------------------
# [ _escape_regex_special_chars method ] (string)
# Private method that escapes special regex metacharacters
# Returns a string with the escaped character modifications
#------------------------------------------------------------------------------
def _escape_regex_special_chars(self, test_escape_string):
return re.escape(test_escape_string)
#------------------------------------------------------------------------------
# Renderer class
# Render the variable replacements in the ink template using a Python dictionary key argument
# Construct the instace of the Renderer with the Ink template and the dictionary key
# Run the renderer with the render method on the instance (e.g. r.render())
# Parameters to constructor:
# - template = an Ink Template instance
# - key = a dictionary mapped key = variable name : value = variable replacement data
# - html_entities = encode html entities with HTML escaped characters (default = False = do not encode)
#------------------------------------------------------------------------------
class Renderer:
def __init__(self, template, key, html_entities=False):
self.odel = template.odel
self.cdel = template.cdel
self.template = template
self.html_entities = html_entities
self.key_dict = key
#------------------------------------------------------------------------------
# [ render method ] (string)
# renders the variable replacements in the Ink template
# returns the rendered template as a string
#------------------------------------------------------------------------------
def render(self):
# make local variables for the loop below (faster)
local_dict = self.key_dict
local_template = self.template
local_varlist = self.template.varlist
local_odel = self.odel
local_cdel = self.cdel
local_htmlent = self.html_entities
if local_htmlent:
from xml.sax.saxutils import escape #from Python std lib
for key in local_dict:
if key in local_varlist:
value = local_dict[key]
replace_string = local_odel + key + local_cdel
if local_htmlent:
value = escape(value) #xml.sax.saxutils function
local_template = local_template.replace(replace_string, value)
return local_template
##TODO : multiple file render method?
if __name__ == '__main__':
pass
# template = Template("This is a of the {{test}} of the {{document}} {{type}} and more of the {{test}} {{document}} {{type}}")
# renderer = Renderer(template, {'test': 'ব য', 'document':'testing document', 'type':'of mine', 'bogus': 'bogus test'})
# print(renderer.render())

@ -0,0 +1,352 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
import sys
import requests
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
#[ HTTP class]
# handle HTTP requests
# Uses the requests external library to handle HTTP requests and response object (available on PyPI)
#------------------------------------------------------------------------------
class HTTP():
def __init__(self, url="", request_timeout=10):
self.url = url
self.request_timeout = request_timeout
#------------------------------------------------------------------------------
# HTTP response properties (assignment occurs with the HTTP request methods)
#------------------------------------------------------------------------------
self.res = None # assigned with the requests external library response object after a HTTP method call
#------------------------------------------------------------------------------
# [ get method ] (string) -
# HTTP GET request - returns text string
# returns data stream read from the URL (string)
# Default timeout = 10 s from class constructor
# Re-throws ConnectionError on failed connection (e.g. no site at URL)
# Test : test_NETWORK.py :: test_http_get, test_http_get_response_change,
# test_http_post_reponse_change, test_http_get_response_check
#------------------------------------------------------------------------------
def get(self, follow_redirects=True):
try:
response = requests.get(self.url, timeout=self.request_timeout, allow_redirects=follow_redirects)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.text
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request with the URL " + self.url + " using the get() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ get_data method ] (binary data)
# HTTP GET request, return binary data
# returns data stream with raw binary data
#------------------------------------------------------------------------------
def get_bin(self):
try:
response = requests.get(self.url, timeout=self.request_timeout)
self.res = response # assign the response object from requests to a property on the instance
return response.content # return binary data instead of text (get() returns text)
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request with the URL " + self.url + " using the get_data() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ get_bin_write_file method ] (boolean)
# open HTTP data stream with GET request, make file with the returned binary data
# file path is passed to the method by the developer
# set suppress_output to True if you want to suppress the d/l status information that is printed to the standard output stream
# return True on successful pull and write to disk
# Tests: test_NETWORK.py :: test_http_get_binary
#------------------------------------------------------------------------------
def get_bin_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...")
sys.stdout.flush()
response = requests.get(self.url, timeout=self.request_timeout, stream=True)
self.res = response
with open(filepath, 'wb') as f: # write as binary data
for chunk in response.iter_content(chunk_size=2048):
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.")
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request and write file with the URL " + self.url + " using the get_bin_write_file() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ get_txt_write_file method ] (boolean)
# open HTTP data stream with GET request, write file with utf-8 encoded text using returned text data
# file path is passed to the method by the developer (default is the base filename in the URL if not specified)
# return True on successful pull and write to disk
# Tests: test_NETWORK.py :: test_http_get_text
#------------------------------------------------------------------------------
def get_txt_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...")
sys.stdout.flush()
response = requests.get(self.url, timeout=self.request_timeout, stream=True)
self.res = response
import codecs
with codecs.open(filepath, mode='w', encoding="utf-8") as f: #write as text
for chunk in response.iter_content(chunk_size=2048):
chunk = chunk.decode('utf-8')
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.")
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request and write file with the URL " + self.url + " using the get_data_write_txt() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ head method ] (dictionary of strings)
# HTTP HEAD request
# returns a dictionary of the header strings
# test for a specific header on either the response dictionary or the instance res property
# Usage example:
# content_type = instance.res['content-type']
# Tests: test_NETWORK.py :: test_http_head
#------------------------------------------------------------------------------
def head(self):
try:
response = requests.head(self.url, timeout=self.request_timeout)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.headers
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform a HEAD request with the head() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post method ] (string)
# HTTP POST request for text
# returns text from the URL as a string
#------------------------------------------------------------------------------
def post(self, follow_redirects=True):
try:
response = requests.post(self.url, timeout=self.request_timeout, allow_redirects=follow_redirects)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.text
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.exit("Naked Framework Error: Unable to perform a POST request with the post() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post_bin method ] (binary data)
# HTTP POST request for binary data
# returns binary data from the URL
#------------------------------------------------------------------------------
def post_bin(self):
try:
response = requests.post(self.url, timeout=self.request_timeout)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.content
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.exit("Naked Framework Error: Unable to perform POST request with the post_bin() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post_bin_write_file method ] (boolean = success of write)
# HTTP POST request, write binary file with the response data
# default filepath is the basename of the URL file, may be set by passing an argument to the method
# returns a boolean that indicates the success of the file write
#------------------------------------------------------------------------------
def post_bin_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...") #provide information about the download to user
sys.stdout.flush()
response = requests.post(self.url, timeout=self.request_timeout, stream=True)
self.res = response
with open(filepath, 'wb') as f: # write as binary data
for chunk in response.iter_content(chunk_size=2048):
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.") # provide user with completion information
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform POST request and write file with the URL " + self.url + " using the post_data_write_bin() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ post_txt_write_file method ] (boolean = success of file write)
# HTTP POST request, write utf-8 encoded text file with the response data
# default filepath is the basename of the URL file, may be set by passing an argument to the method
# returns a boolean that indicates the success of the file write
#------------------------------------------------------------------------------
def post_txt_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...") #provide information about the download to user
sys.stdout.flush()
response = requests.post(self.url, timeout=self.request_timeout, stream=True)
self.res = response
import codecs
with codecs.open(filepath, mode='w', encoding="utf-8") as f: # write as binary data
for chunk in response.iter_content(chunk_size=2048):
chunk = chunk.decode('utf-8')
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.") # provide user with completion information
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform POST request and write file with the URL " + self.url + " using the post_data_write_bin() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ response method ]
# getter method for the requests library object that is assigned as a property
# on the HTTP class after a HTTP request method is run (e.g. get())
# Note: must run one of the HTTP request verbs to assign this property before use of getter (=None by default)
# Tests: test_NETWORK.py :: test_http_get_response_check
#------------------------------------------------------------------------------
def response(self):
try:
return self.res
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to return the response from your HTTP request with the response() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ get_status_ok method ] (boolean)
# return boolean whether HTTP response was in 200 status code range for GET request
# Note: this method runs its own GET request, does not need to be run separately
# Tests: test_NETWORK.py ::
#------------------------------------------------------------------------------
def get_status_ok(self):
try:
self.get() #run the get request
if self.res and self.res.status_code:
return (self.res.status_code == requests.codes.ok)
else:
return False
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to obtain the HTTP status with the get_status_ok() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post_status_ok method ] (boolean)
# return boolean whether HTTP response was in 200 status code range for POST request
# Note: method runs its own post method, not necessary to run separately
#------------------------------------------------------------------------------
def post_status_ok(self):
try:
self.post() #run the post request
if self.res and self.res.status_code:
return (self.res.status_code == requests.codes.ok)
else:
return False
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to obtain the HTTP status with the post_status_ok() method (Naked.toolshed.network.py).")
raise e
if __name__ == '__main__':
pass
#------------------------------------------------------------------------------
# HTTP GET 1
#------------------------------------------------------------------------------
# http = HTTP("http://www.google.com")
# data = http.get()
# print(data)
# from Naked.toolshed.file import FileWriter
# w = FileWriter("testfile.txt")
# w.write_utf8(data)
#------------------------------------------------------------------------------
# HTTP GET 2
#------------------------------------------------------------------------------
# http = HTTP()
# http.url = "http://www.google.com"
# print(http.get())

@ -0,0 +1,53 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=True
from sys import version_info
#------------------------------------------------------------------------------
# Python Versions
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ py_version function ] (tuple of (major, minor, patch))
#------------------------------------------------------------------------------
def py_version():
return (version_info[0], version_info[1], version_info[2])
#------------------------------------------------------------------------------
# [ py_major_version function ] (integer)
# Return Python interpreter major version number
#------------------------------------------------------------------------------
def py_major_version():
return (version_info[0])
#------------------------------------------------------------------------------
# [ py_minor_version function ] (integer)
# Return Python interpreter minor version number
#------------------------------------------------------------------------------
def py_minor_version():
return (version_info[1])
#------------------------------------------------------------------------------
# [ py_patch_version function ] (integer)
# Return Python interpreter patch version number
#------------------------------------------------------------------------------
def py_patch_version():
return (version_info[2])
#------------------------------------------------------------------------------
# [ is_py2 function ] (boolean)
# Return truth result for question is interpreter running a version of Python 2
#------------------------------------------------------------------------------
def is_py2():
return (version_info[0] == (2))
#------------------------------------------------------------------------------
# [ is_py3 function ] (boolean)
# Return truth result for question is interpreter running a version of Python 3
#------------------------------------------------------------------------------
def is_py3():
return (version_info[0] == (3))
if __name__ == '__main__':
pass

@ -0,0 +1,18 @@
from distutils.core import setup
from distutils.extension import Extension
ext_bench = Extension("benchmarking", ["benchmarking.c"])
ext_casts = Extension("casts", ["casts.c"])
ext_file = Extension("file", ["file.c"])
ext_ink = Extension("ink", ["ink.c"])
ext_net = Extension("network", ["network.c"])
ext_py = Extension("python", ["python.c"])
ext_shell = Extension("shell", ["shell.c"])
ext_state = Extension("cstate", ["cstate.c"])
ext_sys = Extension("system", ["system.c"])
ext_types = Extension("types", ["types.c"])
setup(
ext_modules = [ext_bench, ext_casts, ext_file, ext_ink, ext_net, ext_py, ext_shell, ext_state, ext_sys, ext_types]
)

@ -0,0 +1,264 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
import os
import sys
import subprocess
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [ execute function ] (boolean)
# run a shell command and print std out / std err to terminal
# returns True if exit status = 0
# returns False if exit status != 0
#------------------------------------------------------------------------------
def execute(command):
try:
response = subprocess.call(command, shell=True)
if response == 0:
return True
else:
return False
except subprocess.CalledProcessError as cpe:
try:
sys.stderr.write(cpe.output)
except TypeError as te:
sys.stderr.write(str(cpe.output))
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the execute() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ run function ] (bytes string or False)
# run a shell command
# default =
# success:: print to std out and return the std out string
# error:: print to stderr return False, suppress SystemExit on error to permit ongoing run of calling script
# suppress_stdout = True >> suppress std output stream print (returns string)
# suppress_stderr = True >> suppress std err stream print (returns False)
# suppress_exit_status_call = False >> raise SystemExit with the returned status code
#------------------------------------------------------------------------------
def run(command, suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
try:
response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
if not suppress_stdout:
print(response)
return response
except subprocess.CalledProcessError as cpe:
if not suppress_stderr: # error in existing application (non-zero exit status)
try:
sys.stderr.write(cpe.output)
except TypeError as te: # deal with unusual errors from some system executables that return non string type through subprocess.check_output
sys.stderr.write(str(cpe.output))
if not suppress_exit_status_call:
if cpe.returncode:
sys.exit(cpe.returncode)
else:
sys.exit(1)
return False # return False on non-zero exit status codes (i.e. failures in the subprocess executable)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ muterun function ] (NakedObject with attributes for stdout, stderr, exitcode)
# run a shell command and return a response object
# return object attributes : stdout (bytes), stderr (bytes), exitcode (int)
#------------------------------------------------------------------------------
def muterun(command):
try:
from Naked.toolshed.types import NakedObject
response_obj = NakedObject()
response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
response_obj.stdout = response
response_obj.exitcode = 0
response_obj.stderr = b""
return response_obj
except subprocess.CalledProcessError as cpe:
response_obj.stdout = b""
response_obj.stderr = cpe.output
if cpe.returncode:
response_obj.exitcode = cpe.returncode
else:
response_obj.exitcode = 1
return response_obj
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the mute_run() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# RUBY COMMAND EXECUTION
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ execute_rb function ] (boolean)
# execute a ruby script file in a shell subprocess
#------------------------------------------------------------------------------
def execute_rb(file_path, arguments=""):
try:
if len(arguments) > 0:
rb_command = 'ruby ' + file_path + " " + arguments
else:
rb_command = 'ruby ' + file_path
return execute(rb_command) # return result of execute() of the ruby file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_rb() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ run_rb function ] (bytes string or False)
# execute a ruby script file in a shell subprocess, return the output
#------------------------------------------------------------------------------
def run_rb(file_path, arguments="", suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
try:
if len(arguments) > 0:
rb_command = 'ruby ' + file_path + " " + arguments
else:
rb_command = 'ruby ' + file_path
return run(rb_command, suppress_stdout, suppress_stderr, suppress_exit_status_call) # return result of run() of the ruby file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_rb() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ muterun_rb function ] (NakedObject response object)
#------------------------------------------------------------------------------
def muterun_rb(file_path, arguments=""):
try:
if len(arguments) > 0:
rb_command = 'ruby ' + file_path + " " + arguments
else:
rb_command = 'ruby ' + file_path
return muterun(rb_command) # return result of muterun() of the ruby file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the muterun_rb() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# NODE.JS COMMAND EXECUTION
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ execute_js function ] (boolean)
# execute a node.js script file in a shell subprocess
# stdout stream to terminal
# returns True for success (=0) exit status code
# returns False for unsuccessful (!=0) exit status code
#------------------------------------------------------------------------------
def execute_js(file_path, arguments=""):
try:
if len(arguments) > 0:
js_command = 'node ' + file_path + " " + arguments
else:
js_command = 'node ' + file_path
return execute(js_command) # return result of execute() of node.js file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_js() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ run_js function ] (byte string or False)
# execute a node.js script file in a shell subprocess
# print the standard output to the standard output stream by default
# set suppress_output to True to suppress stream to standard output. String is still returned to calling function
# set suppress_exit_status_call to True to suppress raising sys.exit on failures with shell subprocess exit status code (if available) or 1 if not available
# returns the standard output byte string from the subprocess executable on success
# returns False if the subprocess exits with a non-zero exit code
#------------------------------------------------------------------------------
def run_js(file_path, arguments="", suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
try:
if len(arguments) > 0:
js_command = 'node ' + file_path + " " + arguments
else:
js_command = 'node ' + file_path
return run(js_command, suppress_stdout, suppress_stderr, suppress_exit_status_call) # return result of run() of node.js file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_js() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ muterun_js function ] (NakedObject response object)
#------------------------------------------------------------------------------
def muterun_js(file_path, arguments=""):
try:
if len(arguments) > 0:
js_command = 'node ' + file_path + " " + arguments
else:
js_command = 'node ' + file_path
return muterun(js_command) # return result of muterun() of node.js file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the muterun_js() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ Environment Class ]
# shell environment variables class
# self.env = the environment variable dictionary
# self.vars = the environment variable names list
#------------------------------------------------------------------------------
class Environment():
def __init__(self):
self.env = os.environ
self.vars = list(os.environ.keys())
#------------------------------------------------------------------------------
# [ is_var method ] (boolean)
# return boolean for presence of a variable name in the shell environment
#------------------------------------------------------------------------------
def is_var(self, var_name):
try:
return (var_name in self.vars)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to determine if the variable is included in the shell variable list with the is_var() method (Naked.toolshed.shell).")
raise e
#------------------------------------------------------------------------------
# [ get_var method ] (string)
# get the variable value for a variable in the shell environment list
# returns empty string if the variable is not included in the environment variable list
#------------------------------------------------------------------------------
def get_var(self, var_name):
try:
if var_name in self.vars:
return self.env[var_name]
else:
return ""
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return the requested shell variable with the get_var() method (Naked.toolshed.shell).")
raise e
#------------------------------------------------------------------------------
# [ get_split_var_list method ] (list of strings)
# return a list of strings split by OS dependent separator from the shell variable assigment string
# if the variable name is not in the environment list, returns an empty list
#------------------------------------------------------------------------------
def get_split_var_list(self, var_name):
try:
if var_name in self.vars:
return self.env[var_name].split(os.pathsep)
else:
return []
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return environment variable list with the get_split_var_list() method (Naked.toolshed.shell).")
raise e
if __name__ == '__main__':
pass
# e = Environment()
# pathlist = e.get_split_var_list("PATH")
# for item in pathlist:
# print(item)

@ -0,0 +1,554 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
import sys
import os
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
#
# FILE & DIRECTORY PATHS
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ filename function ] (string)
# returns file name from a file path (including the file extension)
# Tests: test_SYSTEM.py :: test_sys_filename
#------------------------------------------------------------------------------
def filename(filepath):
try:
return os.path.basename(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return base filename from filename() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ file_extension function ] (string)
# returns file extension from a filepath
# Tests: test_SYSTEM.py :: test_sys_file_extension
#------------------------------------------------------------------------------
def file_extension(filepath):
try:
return os.path.splitext(filepath)[1]
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return file extension with file_extension() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ directory function ] (string)
# returns directory path to the filepath
# Tests: test_SYSTEM.py :: test_sys_dir_path
#------------------------------------------------------------------------------
def directory(filepath):
try:
return os.path.dirname(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return directory path to file with directory() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ make_path function ] (string)
# returns OS independent file path from tuple of path components
# Tests: test_SYSTEM.py :: test_sys_make_filepath
#------------------------------------------------------------------------------
def make_path(*path_list):
try:
return os.path.join(*path_list)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to make OS independent path with the make_path() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ currentdir_to_basefile decorator function ] (returns decorated original function)
# concatenates the absolute working directory path to the basename of file in the first parameter of the undecorated function
# Tests: test_SYSTEM.py :: test_sys_add_currentdir_path_to_basefile
#------------------------------------------------------------------------------
def currentdir_to_basefile(func):
try:
from functools import wraps
@wraps(func)
def wrapper(file_name, *args, **kwargs):
current_directory = os.getcwd() #get current working directory path
full_path = os.path.join(current_directory, file_name) # join cwd path to the filename for full path
return func(full_path, *args, **kwargs) #return the original function with the full path to file as first argument
return wrapper
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with the currentdir_to_basefile() decorator function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ currentdir_firstparam decorator function ] (returns decorated original function)
# adds the current working directory as the first function parameter of the decorated function
# Tests: test_SYSTEM.py :: test_sys_add_currentdir_path_first_arg
#------------------------------------------------------------------------------
def currentdir_firstparam(func):
try:
from functools import wraps
@wraps(func)
def wrapper(dir="", *args, **kwargs):
current_directory = os.getcwd()
return func(current_directory, *args, **kwargs)
return wrapper
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with the currentdir_firstargument() decorator function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ currentdir_lastargument decorator function ] (returns decorated original function)
# adds the current working directory as the last function parameter of the decorated function
# Note: you cannot use other named arguments in the original function with this decorator
# Note: the current directory argument in the last position must be named current_dir
# Tests: test_SYSTEM.py :: test_sys_add_currentdir_last_arg
#------------------------------------------------------------------------------
def currentdir_lastparam(func):
try:
from functools import wraps
@wraps(func)
def wrapper(*args, **kwargs):
the_cwd = os.getcwd()
return func(*args, current_dir=the_cwd)
return wrapper
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with the currentdir_lastargument() decorator function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ fullpath function ] (string)
# returns the absolute path to a file that is in the current working directory
# file_name = the basename of the file in the current working directory
# Example usage where test.txt is in working directory:
# filepath = fullpath("test.txt")
# Tests: test_SYSTEM.py :: test_sys_full_path_to_file
#------------------------------------------------------------------------------
@currentdir_to_basefile # current directory decorator - adds the directory path up to the filename to the basefile name argument to original function
def fullpath(file_name):
try:
return file_name
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return absolute path to the file with the fullpath() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ cwd function ] (string)
# returns the current working directory path
# does not need to be called with an argument, the decorator assigns it
# Example usage:
# current_dir = cwd()
# Tests: test_SYSTEM.py :: test_sys_cwd_path
#------------------------------------------------------------------------------
@currentdir_firstparam
def cwd(dir=""):
try:
return dir
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return the current working directory with the cwd() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# DIRECTORY WRITES
#
#------------------------------------------------------------------------------
## TODO: add tests
#------------------------------------------------------------------------------
# [ make_dirs function ] (--none--)
# make a new directory path (recursive if multiple levels of depth) if it
# DOES NOT already exist
#------------------------------------------------------------------------------
def make_dirs(dirpath):
try:
import os
import errno
os.makedirs(dirpath)
return True
except OSError as ose:
if ose.errno != errno.EEXIST: # directory already exists
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Could not write the directory path passed as an argument to the make_dirs() function (Naked.toolshed.system).")
raise ose
else:
return False
except Exception as e:
raise e
#------------------------------------------------------------------------------
#
# FILE & DIRECTORY TESTING
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ file_exists function ] (boolean)
# return boolean for existence of file in specified path
# Tests: test_SYSTEM.py :: test_file_exists
#------------------------------------------------------------------------------
def file_exists(filepath):
try:
if os.path.exists(filepath) and os.path.isfile(filepath): # test that exists and is a file
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for the presence of the file with the file_exists() method (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ is_file function ] (boolean)
# returns boolean for determination of whether filepath is a file
# Tests: test_SYSTEM.py :: test_sys_is_file, test_sys_is_file_missing_file,
# test_sys_is_file_when_dir
#------------------------------------------------------------------------------
def is_file(filepath):
try:
return os.path.isfile(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for file with the is_file() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ dir_exists function ] (boolean)
# return boolean for existence of directory in specified path
# Tests: test_SYSTEM.py :: test_dir_exists, test_dir_exists_missing_dir
#------------------------------------------------------------------------------
def dir_exists(dirpath):
try:
if os.path.exists(dirpath) and os.path.isdir(dirpath): # test that exists and is a directory
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for directory with the dir_exists() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ is_dir function ] (boolean)
# returns boolean for determination of whether dirpath is a directory
# Tests: test_SYSTEM.py :: test_sys_dir_is_dir, test_sys_dir_is_dir_when_file,
# test_sys_dir_is_dir_when_missing
#------------------------------------------------------------------------------
def is_dir(dirpath):
try:
return os.path.isdir(dirpath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for directory with the is_dir() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# FILE METADATA
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ filesize function ] (int)
# return file size in bytes
# Tests: test_SYSTEM.py :: test_sys_meta_file_size
#------------------------------------------------------------------------------
def file_size(filepath):
try:
return os.path.getsize(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return file size with the file_size() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ file_mod_time function ] (string)
# return the last file modification date/time
# Tests: test_SYSTEM.py :: test_sys_meta_file_mod
#------------------------------------------------------------------------------
def file_mod_time(filepath):
try:
import time
return time.ctime(os.path.getmtime(filepath))
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return file modification data with the file_mod_time() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# FILE LISTINGS
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ list_all_files function ] (list)
# returns a list of all files in developer specified directory
# Tests: test_SYSTEM.py :: test_sys_list_all_files, test_sys_list_all_files_emptydir
#------------------------------------------------------------------------------
def list_all_files(dir):
try:
filenames = [name for name in os.listdir(dir) if os.path.isfile(os.path.join(dir, name))]
return filenames
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to generate directory file list with the list_all_files() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_filter_files function ] (list)
# returns a list of files filtered by developer defined file extension in developer defined directory
# Usage example:
# filenames = list_filter_files("py", "tests")
# Tests: test_SYSTEM.py :: test_sys_list_filter_files, test_sys_list_filter_files_nomatch
#------------------------------------------------------------------------------
def list_filter_files(extension_filter, dir):
try:
if not extension_filter.startswith("."):
extension_filter = "." + extension_filter
filenames = [name for name in os.listdir(dir) if name.endswith(extension_filter)]
return filenames
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of filtered files with the list_filter_files() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_all_files_cwd function ] (list)
# returns a list of all files in the current working directory
# Note: does not require argument, the decorator assigns the cwd
# Usage example:
# file_list = list_all_files_cwd()
# Tests: test_SYSTEM.py :: test_sys_list_all_files_cwd
#------------------------------------------------------------------------------
@currentdir_firstparam
def list_all_files_cwd(dir=""):
try:
return list_all_files(dir)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of all files in current working directory with the list_all_files_cwd() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_filter_files_cwd function ] (list)
# returns a list of all files in the current working directory filtered by developer specified file extension
# Note: do not specify the second argument, decorator assigns it
# Usage example:
# file_list = list_filter_files_cwd(".py")
# Tests: test_SYSTEM.py :: test_sys_filter_files_cwd, test_sys_filter_files_cwd_nomatch
#------------------------------------------------------------------------------
@currentdir_lastparam
def list_filter_files_cwd(extension_filter, current_dir=""):
try:
return list_filter_files(extension_filter, current_dir)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of filtered files in current working directory with the list_filter_files_cwd() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_match_files function ] (list)
# returns a list of all files that match the developer specified wildcard match pattern
# can optionally specify return of full path to the files (rather than relative path from cwd) by setting full_path to True
# Usage examples:
# file_list = list_match_files("*.py")
# file_list_fullpath = list_match_files("*.py", True)
# Tests: test_SYSTEM.py :: test_sys_match_files, test_sys_match_files_fullpath
#------------------------------------------------------------------------------
def list_match_files(match_pattern, full_path = False):
try:
from glob import glob
filenames = glob(match_pattern)
if full_path:
filenames_fullpath = []
cwd = os.getcwd()
for name in filenames:
name = os.path.join(cwd, name) #make the full path to the file
filenames_fullpath.append(name) #add to the new list
return filenames_fullpath #then return that list
else:
return filenames
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of matched files with the list_match_files() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# SYMBOLIC LINK TESTING
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ is_link function ] (boolean)
# return boolean indicating whether the path is a symbolic link
#------------------------------------------------------------------------------
def is_link(filepath):
try:
return os.path.islink(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to determine whether path is a symbolic link with the is_link() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ real_path function ] (string)
# return the real file path pointed to by a symbolic link
#------------------------------------------------------------------------------
def real_path(filepath):
try:
return os.path.realpath(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return real path for symbolic link with the real_path() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# DATA STREAMS
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ stdout function ]
# print to std output stream
#------------------------------------------------------------------------------
def stdout(text):
try:
print(text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stdout_xnl function ]
# print to std output stream without a newline
#------------------------------------------------------------------------------
def stdout_xnl(text):
try:
sys.stdout.write(text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_xnl() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stdout_iter function ]
# print items in an iterable to the standard output stream with newlines after each string
#------------------------------------------------------------------------------
def stdout_iter(iter):
try:
for x in iter:
stdout(x)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_iter() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stdout_iter_xnl function ]
# print items in an iterable to the standard output stream without newlines after each string
#------------------------------------------------------------------------------
def stdout_iter_xnl(iter):
try:
for x in iter:
stdout_xnl(x)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_iter() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stderr function ]
# print to std error stream
# optionally (i.e. if exit = nonzero integer) permits exit from application with developer defined exit code
#------------------------------------------------------------------------------
def stderr(text, exit=0):
try:
sys.stderr.write(text + "\n")
if exit:
raise SystemExit(exit)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard error stream with the stderr() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stderr_xnl function ]
# print to the standard error stream without a newline character after the `text` string
#------------------------------------------------------------------------------
def stderr_xnl(text, exit=0):
try:
sys.stderr.write(text)
if exit:
raise SystemExit(exit)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard error stream with the stderr() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# APPLICATION CONTROL
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ exit_with_status function ]
# application exit with developer specified exit status code (default = 0)
# use an exit status integer argument
# Tests: test_SYSTEM.py :: test_sys_exit_with_code
#------------------------------------------------------------------------------
def exit_with_status(exit=0):
raise SystemExit(exit)
#------------------------------------------------------------------------------
# [ exit_fail function ]
# application exit with status code 1
# Tests: test_SYSTEM.py :: test_sys_exit_failure
#------------------------------------------------------------------------------
def exit_fail():
raise SystemExit(1)
#------------------------------------------------------------------------------
# [ exit_success function]
# application exit with status code 0
# Tests: test_SYSTEM.py :: test_sys_exit_success
#------------------------------------------------------------------------------
def exit_success():
raise SystemExit(0)
if __name__ == '__main__':
pass
# #------------------------------------------------------------------------------
# # Standard Output Tests
# #------------------------------------------------------------------------------
# stdout("This is a test")
# for x in range(10):
# stdout_xnl(str(x) + " ")
# list_ten = ['10% ', '20% ', '30% ', '40% ', '50% ', '60% ', '70% ', '80% ', '90% ', '100%']
# stdout_iter(list_ten)
# #------------------------------------------------------------------------------
# # Standard Error Tests
# #------------------------------------------------------------------------------
# stderr("This is a test")
# stderr("This is a test", 1) #exit with status code 1

@ -0,0 +1,999 @@
#!/usr/bin/env python
# encoding: utf-8
# cython: profile=False
import sys
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [[ NakedObject class ]]
# A generic Python object
# Assigns object attributes by key name in the dictionary argument to the constructor
# The methods are inherited by other mutable Naked object extension types
# Attribute accessors: hasattr, getattr, setattr, delattr
#------------------------------------------------------------------------------
class NakedObject(object):
# initialize with an attributes dictionary {attribute_name: attribute_value}
def __init__(self, attributes={}, naked_type='NakedObject'):
if len(attributes) > 0:
for key in attributes:
setattr(self, key, attributes[key])
setattr(self, '_naked_type_', naked_type) # maintain an attribute to keep track of the extension type
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the NakedObject instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ _equal_type method ] (boolean)
# returns boolean for type of instance == type of test parameter instance
#------------------------------------------------------------------------------
def _equal_type(self, other_obj):
return type(self) == type(other_obj)
#------------------------------------------------------------------------------
# [ _equal_attributes metod ] (method)
# returns boolean for instance.__dict__ == test parameter .__dict__ (attribute comparison)
#------------------------------------------------------------------------------
def _equal_attributes(self, other_obj):
return self.__dict__ == other_obj.__dict__
#------------------------------------------------------------------------------
# == overload
#------------------------------------------------------------------------------
def __eq__(self, other_obj):
return self.equals(other_obj)
#------------------------------------------------------------------------------
# != overload
#------------------------------------------------------------------------------
def __ne__(self, other_obj):
result = self.equals(other_obj)
if result:
return False # reverse result of the equals method
else:
return True
#------------------------------------------------------------------------------
# [ equals method ] (boolean)
# equality testing based on type and attributes
# **NEED TO OVERRIDE IN CLASSES THAT INHERIT
#------------------------------------------------------------------------------
def equals(self, other_obj):
return self._equal_type(other_obj) and self._equal_attributes(other_obj)
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
#------------------------------------------------------------------------------
# [[ XDict class ]]
# An inherited extension to the dictionary type
#------------------------------------------------------------------------------
class XDict(dict, NakedObject):
def __init__(self, dict_obj, attributes={}, naked_type='XDict'):
dict.__init__(self, dict_obj)
NakedObject.__init__(self, attributes, naked_type)
#------------------------------------------------------------------------------
# XDict Operator Overloads
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# + overload
# overwrites existing keys with key:value pairs from new dictionaries if they are the same keys
# returns the updated XDict object
#------------------------------------------------------------------------------
def __add__(self, other_dict):
try:
self.update(other_dict)
if hasattr(other_dict, '_naked_type_') and (getattr(other_dict, '_naked_type_') == 'XDict'):
attr_dict = other_dict._getAttributeDict() # get the attributes from the parameter XDict and add to new XDict
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XDict with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# +- overload
# overwrites existing keys with another_dict (right sided argument) keys if they are the same keys
# returns the updated XDict object
#------------------------------------------------------------------------------
def __iadd__(self, other_dict):
try:
self.update(other_dict)
if hasattr(other_dict, '_naked_type_') and (getattr(other_dict, '_naked_type_') == 'XDict'):
attr_dict = other_dict._getAttributeDict() # get the attributes from the parameter XDict and add to new XDict
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XDict with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# == overload
#------------------------------------------------------------------------------
def __eq__(self, other_obj):
return self.equals(other_obj)
#------------------------------------------------------------------------------
# != overload
#------------------------------------------------------------------------------
def __ne__(self, other_obj):
result = self.equals(other_obj)
if result:
return False # reverse result of the equals method
else:
return True
#------------------------------------------------------------------------------
# [ equals method ] (boolean)
# tests for equality of the XDict (type, attributes, dictionary equality)
#------------------------------------------------------------------------------
def equals(self, other_obj):
if self._equal_type(other_obj) and self._equal_attributes(other_obj):
if dict(self) == dict(other_obj):
return True
else:
return False
else:
return False
#------------------------------------------------------------------------------
# XDict Value Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ conditional_map_to_vals method ] (XDict)
# returns the original XDict with values that meet True condition in `conditional_function`
# modified as per the `mapped_function` with single value argument call
# Test: test_xdict_conditional_map
#------------------------------------------------------------------------------
def conditional_map_to_vals(self, conditional_function, mapped_function):
for key, value in self.xitems():
if conditional_function(key):
self[key] = mapped_function(value)
return self
#------------------------------------------------------------------------------
# [ map_to_vals method ] (XDict)
# returns the original XDict with all values modified as per the `mapped_function`
# Test: test_xdict_map_to_vals
#------------------------------------------------------------------------------
def map_to_vals(self, mapped_function):
# return XDict( zip(self, map(mapped_function, self.values())), self._getAttributeDict() ) - slower in Py2
for key, value in self.xitems():
self[key] = mapped_function(value)
return self
#------------------------------------------------------------------------------
# [ val_xlist method ] (XList)
# return an XList of the values in the XDict
# Test: test_xdict_val_xlist
#------------------------------------------------------------------------------
def val_xlist(self):
return XList(self.values(), self._getAttributeDict())
#------------------------------------------------------------------------------
# [ max_val method ] (tuple of maximum value and associated key)
# Test: test_xdict_max_val, test_xdict_max_val_strings (strings are alphabetic if not numerals)
#------------------------------------------------------------------------------
def max_val(self):
return max(zip(self.values(), self.keys()))
#------------------------------------------------------------------------------
# [ min_val method ] (tuple of minimum value and associated key)
#------------------------------------------------------------------------------
def min_val(self):
return min(zip(self.values(), self.keys()))
#------------------------------------------------------------------------------
# [ sum_vals method ] (numeric return type dependent upon original value type)
# returns sum of all values in the dictionary
#------------------------------------------------------------------------------
def sum_vals(self):
return sum(self.values())
#------------------------------------------------------------------------------
# [ val_count method ] (integer)
# returns an integer value for the total count of `value_name` in the dictionary values
# Case sensitive test if comparing strings
# Tests: test_xdict_val_count_string, test_xdict_val_count_integer
#------------------------------------------------------------------------------
def val_count(self, value_name):
count = 0
for test_value in self.values():
if value_name == test_value:
count += 1
return count
#------------------------------------------------------------------------------
# [ value_count_ci method ] (integer)
# returns an integer value for the total count of case insensitive `value_name`
# strings/char in the dictionary values. Can include non-string types (ignores them)
# Test: test_xdict_val_count_ci
#------------------------------------------------------------------------------
def val_count_ci(self, value_name):
count = 0
for test_value in self.values():
try:
if value_name.lower() in test_value.lower():
count += 1
except AttributeError: # the test_value was not a string, catch exception and continue count attempt
continue
return count
#------------------------------------------------------------------------------
# XDict Key Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ difference method ] (difference set of keys)
# definition: keys that are included in self, but not in `another_dict`
# Tests: test_xdict_key_difference, test_xdict_key_difference_when_none_present
#------------------------------------------------------------------------------
def difference(self, another_dict):
return set(self.keys()) - set(another_dict.keys())
#------------------------------------------------------------------------------
# [ intersection method ] (intersection set of keys)
# definition: keys that are included in both self and `another_dict`
# Tests: test_xdict_key_intersection, test_xdict_key_intersection_when_none_present
#------------------------------------------------------------------------------
def intersection(self, another_dict):
return set(self.keys()) & set(another_dict.keys())
#------------------------------------------------------------------------------
# [ key_xlist method ] (XList)
# returns an XList of the keys in the XDict
# Test: test_xdict_key_xlist
#------------------------------------------------------------------------------
def key_xlist(self):
return XList(self.keys(), self._getAttributeDict())
#------------------------------------------------------------------------------
# [ random method ] (dictionary)
# return new Python dictionary with single, random key:value pair
# Test: test_xdict_key_random
#------------------------------------------------------------------------------
def random(self):
import random
from Naked.toolshed.python import py_major_version
random_key_list = random.sample(self.keys(), 1)
the_key = random_key_list[0]
return {the_key: self[the_key]}
#------------------------------------------------------------------------------
# [ random_sample method ] (dictionary)
# return new Python dictionary with `number_of_items` random key:value pairs
# Test: test_xdict_key_random_sample
#------------------------------------------------------------------------------
def random_sample(self, number_of_items):
import random
random_key_list = random.sample(self.keys(), number_of_items)
new_dict = {}
for item in random_key_list:
new_dict[item] = self[item]
return new_dict
#------------------------------------------------------------------------------
# [ xitems method ] (tuple)
# Generator method that returns tuples of every key, value in dictionary
# uses appropriate method from Python 2 and 3 interpreters
# Test: test_xdict_xitems
#------------------------------------------------------------------------------
def xitems(self):
from Naked.toolshed.python import py_major_version
if py_major_version() > 2:
return self.items()
else:
return self.iteritems()
#------------------------------------------------------------------------------
# [[ XList class ]]
# An inherited extension to the list object that permits attachment of attributes
#------------------------------------------------------------------------------
class XList(list, NakedObject):
def __init__(self, list_obj, attributes={}, naked_type='XList'):
list.__init__(self, list_obj)
NakedObject.__init__(self, attributes, naked_type)
#------------------------------------------------------------------------------
# XList Operator Overloads
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# + operator overload
# extends XList with one or more other lists (`*other_lists`)
#------------------------------------------------------------------------------
def __add__(self, *other_lists):
try:
for the_list in other_lists:
# add attributes if it is an XList
if hasattr(the_list, '_naked_type_') and (getattr(the_list, '_naked_type_') == 'XList'):
attr_dict = the_list._getAttributeDict() # get XList attribute dictionary
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
# extend the XList items
self.extend(the_list)
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XList with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# += overload
# extends XList with one other list (`another_list`)
#------------------------------------------------------------------------------
def __iadd__(self, another_list):
try:
#add attributes if it is an XList
if hasattr(another_list, '_naked_type_') and (getattr(another_list, '_naked_type_') == 'XList'):
attr_dict = another_list._getAttributeDict() # get XList attribute dictionary
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
# extend the XList items
self.extend(another_list)
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XList with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# == overload
#------------------------------------------------------------------------------
def __eq__(self, other_obj):
return self.equals(other_obj)
#------------------------------------------------------------------------------
# != overload
#------------------------------------------------------------------------------
def __ne__(self, other_obj):
result = self.equals(other_obj)
if result:
return False # reverse result of the equals method
else:
return True
#------------------------------------------------------------------------------
# [ equals method ] (boolean)
# tests for equality of the XList (type, attributes, list equality)
#------------------------------------------------------------------------------
def equals(self, other_obj):
if self._equal_type(other_obj) and self._equal_attributes(other_obj):
if list(self) == list(other_obj):
return True
else:
return False
else:
return False
#------------------------------------------------------------------------------
# XList Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# XList String Methods
#------------------------------------------------------------------------------
# [ join method ] (string)
# Concatenate strings in the list and return
# Default separator between string list values is an empty string
# Pass separator character(s) as an argument to the method
#------------------------------------------------------------------------------
def join(self, separator=""):
return separator.join(self)
#------------------------------------------------------------------------------
# [ postfix method ] (list of strings)
# Append a string to each list item string
#------------------------------------------------------------------------------
def postfix(self, after):
return [ "".join([x, after]) for x in self ]
#------------------------------------------------------------------------------
# [ prefix method ] (list of strings)
# Prepend a string to each list item string
#------------------------------------------------------------------------------
def prefix(self, before):
return [ "".join([before, x]) for x in self ]
#------------------------------------------------------------------------------
# [ surround method ] (list of strings)
# Surround each list item string with a before and after string argument passed to the method
#------------------------------------------------------------------------------
def surround(self, before, after=""):
if after == "":
after = before
return [ "".join([before, x, after]) for x in self ]
#------------------------------------------------------------------------------
# XList Numeric Methods
#------------------------------------------------------------------------------
# [ max method ] (list dependent type, single value)
# return maximum value from the list items
#------------------------------------------------------------------------------
def max(self):
return max(self)
#------------------------------------------------------------------------------
# [ min method ] (list dependent type, single value)
# return minimum value from the list items
#------------------------------------------------------------------------------
def min(self):
return min(self)
#------------------------------------------------------------------------------
# [ sum method ] (list dependent type, single value)
# return the sum of all list items
#------------------------------------------------------------------------------
def sum(self):
return sum(self)
#------------------------------------------------------------------------------
# XList Data Management Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ count_duplicates method ] (integer)
# returns an integer count of number of duplicate values
#------------------------------------------------------------------------------
def count_duplicates(self):
return len(self) - len(set(self))
#------------------------------------------------------------------------------
# [ remove_duplicates ] (XList)
# returns a new XList with duplicates removed
#------------------------------------------------------------------------------
def remove_duplicates(self):
return XList( set(self), self._getAttributeDict() )
#------------------------------------------------------------------------------
# [ difference method ] (set)
# returns a set containing items in XList that are not contained in `another_list`
#------------------------------------------------------------------------------
def difference(self, another_list):
return set(self) - set(another_list)
#------------------------------------------------------------------------------
# [ intersection method ] (set)
# returns a set containing items that are in both XList and `another_list`
#------------------------------------------------------------------------------
def intersection(self, another_list):
return set(self) & set(another_list)
#------------------------------------------------------------------------------
# XList Function Mapping Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ map_to_items method ] (XList)
# returns original XList with modification of each item based upon `mapped_function`
#------------------------------------------------------------------------------
def map_to_items(self, mapped_function):
# return XList( map(mapped_function, self), self._getAttributeDict() ) - slower
for index, item in enumerate(self):
self[index] = mapped_function(item)
return self
#------------------------------------------------------------------------------
# [ conditional_map_to_items method ] (XList)
# returns original XList with modification of items that meet True condition in
# `conditional_function` with change performed as defined in `mapped_function`
#------------------------------------------------------------------------------
def conditional_map_to_items(self, conditional_function, mapped_function):
for index, item in enumerate(self):
if conditional_function(item):
self[index] = mapped_function(item)
return self
#------------------------------------------------------------------------------
# XList Descriptive Stats Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ count_ci method ] (integer)
# returns an integer count of the number of case-insensitive items that match `test_string`
#------------------------------------------------------------------------------
def count_ci(self, test_string):
count = 0
for item in self:
try:
if test_string.lower() in item.lower():
count += 1
except AttributeError: # the test_value was not a string, catch exception and continue count attempt
continue
return count
#------------------------------------------------------------------------------
# [ random method ] (list)
# returns a single item list with a random element from the original XList
#------------------------------------------------------------------------------
def random(self):
import random
return random.choice(self)
#------------------------------------------------------------------------------
# [ random_sample method ] (list)
# returns a list with one or more random items from the original XList
# number of items determined by the `number_of_items` argument
#------------------------------------------------------------------------------
def random_sample(self, number_of_items):
import random
return random.sample(self, number_of_items)
#------------------------------------------------------------------------------
# [ shuffle method ] (XList)
# randomly shuffle the contents of the list
#------------------------------------------------------------------------------
def shuffle(self):
import random
random.shuffle(self)
return self
#------------------------------------------------------------------------------
# XList Match Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ wildcard_match method ] (list)
# returns a list of items that match the `wildcard` argument
#------------------------------------------------------------------------------
def wildcard_match(self, wildcard):
if hasattr(self, 'nkd_fnmatchcase'):
fnmatchcase = self.nkd_fnmatchcase
else:
from fnmatch import fnmatchcase
self.nkd_fnmatchcase = fnmatchcase
return [ x for x in self if fnmatchcase(x, wildcard) ]
#------------------------------------------------------------------------------
# [ multi_wildcard_match method ] (list)
# returns a list of items that match one or more | separated wildcards passed as string
#------------------------------------------------------------------------------
def multi_wildcard_match(self, wildcards):
if hasattr(self, 'nkd_fnmatchcase'):
fnmatchcase = self.nkd_fnmatchcase
else:
from fnmatch import fnmatchcase
self.nkd_fnmatchcase = fnmatchcase
wc_list = wildcards.split('|')
return_list = []
for wc in wc_list:
temp_list = [ x for x in self if fnmatchcase(x, wc) ]
for result in temp_list:
return_list.append(result)
return return_list
#------------------------------------------------------------------------------
# XList Cast Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ xset method ] (XSet)
# return an XSet with unique XList item values and XList attributes
#------------------------------------------------------------------------------
def xset(self):
attr_dict = self._getAttributeDict()
return XSet(set(self), attr_dict)
#------------------------------------------------------------------------------
# [ xfset method ] (XFSet)
# return an XFSet with unique XList item values and XList attributes
#------------------------------------------------------------------------------
def xfset(self):
attr_dict = self._getAttributeDict()
return XFSet(set(self), attr_dict)
#------------------------------------------------------------------------------
# [ xtuple method ] (XTuple)
# returns an XTuple with XList item values and XList attributes
#------------------------------------------------------------------------------
def xtuple(self):
attr_dict = self._getAttributeDict()
return XTuple(tuple(self), attr_dict)
#------------------------------------------------------------------------------
# [[ XMaxHeap class ]]
# max heap queue
#------------------------------------------------------------------------------
from heapq import heappush, heappop
class XMaxHeap(NakedObject):
def __init__(self, attributes={}, naked_type='XMaxHeap'):
NakedObject.__init__(self, attributes, naked_type)
self._queue = []
self._index = 0
# length of the queue
def __len__(self):
return len(self._queue)
# O(log n) complexity
def push(self, the_object, priority):
heappush(self._queue, (-priority, self._index, the_object))
self._index += 1
# O(log n) complexity
def pop(self):
if self._queue:
return heappop(self._queue)[-1]
else:
return None
# push new object and return the highest priority object
def pushpop(self, the_object, priority):
heappush(self._queue, (-priority, self._index, the_object))
self._index += 1
if self._queue:
return heappop(self._queue)[-1]
else:
return None # return None if the queue is empty
# the length of the queue
def length(self):
return len(self._queue)
#------------------------------------------------------------------------------
# [[ XMinHeap class ]]
# min heap queue
#------------------------------------------------------------------------------
from heapq import heappush, heappop
class XMinHeap(NakedObject):
def __init__(self, attributes={}, naked_type='XMinHeap'):
NakedObject.__init__(self, attributes, naked_type)
self._queue = []
self._index = 0
# length of the queue
def __len__(self):
return len(self._queue)
# O(log n) complexity
def push(self, the_object, priority):
heappush(self._queue, (priority, self._index, the_object))
self._index += 1
# O(log n) complexity
def pop(self):
if self._queue:
return heappop(self._queue)[-1]
else:
return None # return None if the queue is empty
# push new object and return the lowest priority object
def pushpop(self, the_object, priority):
heappush(self._queue, (priority, self._index, the_object))
self._index += 1
if self._queue:
return heappop(self._queue)[-1]
else:
return None #return None if the queue is empty
# the length of the queue
def length(self):
return len(self._queue)
#------------------------------------------------------------------------------
# [[ XQueue class ]]
#
#------------------------------------------------------------------------------
from collections import deque
class XQueue(deque, NakedObject):
def __init__(self, initial_iterable=[], attributes={}, max_length=10, naked_type='XQueue'):
deque.__init__(self, initial_iterable, max_length)
NakedObject.__init__(self, attributes, naked_type)
#------------------------------------------------------------------------------
# [[ XSet class ]]
# An inherited extension to the mutable set object that permits attribute assignment
# Inherits from set and from NakedObject (see methods in NakedObject at top of this module
#------------------------------------------------------------------------------
class XSet(set, NakedObject):
def __init__(self, set_obj, attributes={}, naked_type='XSet'):
set.__init__(self, set_obj)
NakedObject.__init__(self, attributes, naked_type)
# << operator is overloaded to extend the XSet with a second set
def __lshift__(self, another_set):
self.update(another_set)
return self
# += operator overload to extend the XSet with a second set
def __iadd__(self, another_set):
self.update(another_set)
return self
def xlist(self):
attr_dict = self._getAttributeDict()
return XList(list(self), attr_dict)
def xfset(self):
attr_dict = self._getAttributeDict()
return XFSet(self, attr_dict)
#------------------------------------------------------------------------------
# [[ XFSet class ]]
# An inherited extension to the immutable frozenset object that permits attribute assignment
# Immutable so there is no setter method, attributes must be set in the constructor
#------------------------------------------------------------------------------
class XFSet(frozenset):
def __new__(cls, the_set, attributes={}, naked_type="XFSet"):
set_obj = frozenset.__new__(cls, the_set)
if len(attributes) > 0:
for key in attributes:
setattr(set_obj, key, attributes[key])
setattr(set_obj, '_naked_type_', naked_type) # set the naked extension type as an attribute (NakedObject does this for mutable classes)
return set_obj
def _getAttributeDict(self):
return self.__dict__
def xlist(self):
attr_dict = self._getAttributeDict()
return XList(list(self), attr_dict, naked_type="XList")
def xset(self):
attr_dict = self._getAttributeDict()
return XSet(self, attr_dict, naked_type="XSet")
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
#------------------------------------------------------------------------------
# [[ XString class ]]
# An inherited extension to the immutable string object that permits attribute assignment
# Immutable so there is no setter method, attributes must be set in the constructor
# Python 2: byte string by default, can cast to normalized UTF-8 with XString().unicode() method
# Python 3: string (that permits unicode) by default, can normalize with XString().unicode() method
#------------------------------------------------------------------------------
class XString(str):
def __new__(cls, string_text, attributes={}, naked_type='XString'):
str_obj = str.__new__(cls, string_text)
if len(attributes) > 0:
for key in attributes:
setattr(str_obj, key, attributes[key])
setattr(str_obj, '_naked_type_', naked_type)
return str_obj
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the XString instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
## TODO: see where + vs. join breakpoint becomes important
def concat(self, *strings):
str_list = []
for x in strings:
str_list.append(x)
return "".join(str_list)
# fastest substring search truth test
def contains(self, substring):
return substring in self
# split the string on one or more delimiters, return list
# if up to two chars, then uses str.split(), if more chars then use re.split
def xsplit(self, split_delimiter):
length = len(split_delimiter)
if length > 2:
import re
split_delimiter = "".join([ '[', split_delimiter, ']' ])
return re.split(split_delimiter, self)
elif length > 1:
delim2 = split_delimiter[1]
first_list = self.split(split_delimiter[0])
result_list = []
for item in first_list:
for subitem in item.split(delim2):
result_list.append(subitem)
return result_list
else:
return self.split(split_delimiter)
# split the string on one or more characters and return items in set
def xsplit_set(self, split_delimiter):
return set(self.xsplit(split_delimiter))
# str begins with substring - faster than str.startswith()
def begins(self, begin_string):
return begin_string in self[0:len(begin_string)]
# str ends with substring - faster than str.endswith()
def ends(self, end_string):
return end_string in self[-len(end_string):]
# case sensitive wildcard match on the XString (boolean returned)
def wildcard_match(self, wildcard):
from fnmatch import fnmatchcase
return fnmatchcase(self, wildcard)
# convert string to normalized UTF-8 in Python 2 and 3 (##TODO: convert to XUnicode with attributes?)
def unicode(self):
from sys import version_info
from unicodedata import normalize
if version_info[0] == 2:
return normalize('NFKD', self.decode('UTF-8'))
else:
return normalize('NFKD', self)
# this version works
class XUnicode:
def __init__(self, string_text, attributes={}, naked_type='XUnicode'):
import sys
import unicodedata
norm_text = unicodedata.normalize('NFKD', string_text)
class XUnicode_2(unicode):
def __new__(cls, the_string_text, attributes={}, naked_type='XUnicode2'):
str_obj = unicode.__new__(cls, the_string_text)
if len(attributes) > 0:
for key in attributes:
setattr(str_obj, key, attributes[key])
setattr(str_obj, '_naked_type_', naked_type) # set the type to XUnicode2 for Py 2 strings
return str_obj
class XUnicode_3(str):
def __new__(cls, the_string_text, attributes={}, naked_type='XUnicode3'):
str_obj = str.__new__(cls, the_string_text)
if len(attributes) > 0:
for key in attributes:
setattr(str_obj, key, attributes[key])
setattr(str_obj, '_naked_type_', naked_type) # set the type to XUnicode3 for Py 3 strings
return str_obj
if sys.version_info[0] == 2:
self.obj = XUnicode_2(norm_text, attributes)
self.norm_unicode = norm_text
self.naked_u_string = self.obj.encode('utf-8') # utf-8 encoded byte string
elif sys.version_info[0] == 3:
self.naked_u_string = XUnicode_3(norm_text, attributes).encode('utf-8') # ?
def __str__(self):
# return self.naked_u_string
return self.obj
def __repr__(self):
return self.naked_u_string
def __getattr__(self, the_attribute):
return self.obj.__dict__[the_attribute]
def __cmp__(self, other_string):
return hash(self.naked_u_string) == hash(other_string)
# TODO: add check for same attributes
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the NakedObject instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
#------------------------------------------------------------------------------
# [[ XTuple class ]]
#
#------------------------------------------------------------------------------
class XTuple(tuple):
def __new__(cls, the_tuple, attributes={}, naked_type='XTuple'):
tup_obj = tuple.__new__(cls, the_tuple)
if len(attributes) > 0:
for key in attributes:
setattr(tup_obj, key, attributes[key])
setattr(tup_obj, '_naked_type_', naked_type)
return tup_obj
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the NakedObject instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
if __name__ == '__main__':
pass
# no = nobj({"version":"1.0.1", "test":"code"})
# print(no)
# print(no.version)
# print(no.test)
# nl = XList([1, 2, 3, 1, 2, 5], {"version":"1.0.1", "test":"code"})
# print(nl.count_duplicates())
# the_list = list(range(5000))
# nl = XList(the_list)
# nq = XPriorityQueue()
# nq.push('test', 5)
# nq.push('one', 3)
# nq.push('another', 4)
# print(nq.pop())
# print(nq.pop())
# print(nq.pop())
# nl = XList([2, 2, 2, 'another'], {'p': 'attribute'})
# print(nl)
# print(nl.count_item(2))
# nq = XQueue(nl, max_length=2)
# print(nq)
# xs = XSet({'test', 'true', 'false'}, {'bonus': 'candy', 'test': 'another'})
# xs += {'bogus', 'yep'}
# print(xs)
# xd = XDict({'test2': 0, 'is': 1}, {'a': '1', 'b': '2'})
# ad = {'test': 0, 'is': 2}
# ld = xd.intersection(ad)
# print(ld)
# xd = xd + ad + ld
# print(xd.map_to_vals(pr))
# print(xd.a)
# print(xd)
# print(xd.a)
# print(xd.min_val())
# print(xd.conditional_map_to_vals(matcher, resulter))
# nl = XList([ 'test.txt', 'bogus.txt', 'test.py', 'another.rb', 'est.doc', 'est.py' ])
# print(nl.multi_wildcard_match('*.py|*.txt|*.doc'))
# xstr = XString("Hey! Cœur It's Bengali ব য,\nand here is some more ২")
# ustr = xstr.unicode()
# print(isinstance(ustr, bytes))
# print(xstr)

@ -0,0 +1,119 @@
#!/usr/bin/env python
# encoding: utf-8
# tests in test_CASTS.py
from Naked.toolshed.types import NakedObject, XFSet, XDict, XList, XQueue, XSet, XString, XTuple
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [ nobj ] (NakedObject)
# Cast a dictionary of attributes to a NakedObject with key>attribute mapping
#------------------------------------------------------------------------------
def nobj(attributes={}):
try:
return NakedObject(attributes)
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to create a NakedObject with the requested argument using the nobj() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xd function ] (XDict)
# Cast a Python dictionary to a XDict
#------------------------------------------------------------------------------
def xd(dictionary_arg, attributes={}):
try:
return XDict(dictionary_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XDict with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XDict with the xd() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xl function ] (XList)
# Cast a Python list, set, or tuple to a XList
#------------------------------------------------------------------------------
def xl(list_arg, attributes={}):
try:
return XList(list_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XList with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XList with the xl() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xq function ] (XQueue)
# Cast a Python list, set, tuple to a XQueue
#------------------------------------------------------------------------------
def xq(queue_arg, attributes={}):
try:
return XQueue(queue_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XQueue with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XQueue with the xq() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xset function ] (XSet)
# Cast a Python set to a XSet
#------------------------------------------------------------------------------
def xset(set_arg, attributes={}):
try:
return XSet(set_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XSet with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XSet with the xset() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xfset function ] (XFSet)
# Cast a Python set to a XFSet
#------------------------------------------------------------------------------
def xfset(set_arg, attributes={}):
try:
return XFSet(set_arg, attributes)
except TypeError:
raise TypeError("Attempted to cast to a XSet with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XSet with the xset() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xstr function ] (XString)
# Cast a Python string to a XString
#------------------------------------------------------------------------------
def xstr(string_arg, attributes={}):
try:
return XString(string_arg, attributes)
except TypeError as te:
raise TypeError("Attempted to cast to a XString with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XString with the xstr() function (Naked.toolshed.casts.py).")
raise e
#------------------------------------------------------------------------------
# [ xt function ] (XTuple)
# Cast a Python list, set, tuple to a XTuple
#------------------------------------------------------------------------------
def xt(tup_arg, attributes={}):
try:
return XTuple(tup_arg, attributes)
except TypeError as te:
raise TypeError("Attempted to cast to a XTuple with an incompatible type")
except Exception as e:
if DEBUG_FLAG:
print("Naked Framework Error: unable to cast object to a XTuple with the xt() function (Naked.toolshed.casts.py).")
raise e
if __name__ == '__main__':
pass

@ -0,0 +1,376 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [ IO class ]
# interface for all local file IO classes
#------------------------------------------------------------------------------
class IO:
def __init__(self,filepath):
self.filepath = filepath
#------------------------------------------------------------------------------
# [ FileWriter class ]
# writes data to local files
#------------------------------------------------------------------------------
class FileWriter(IO):
def __init__(self, filepath):
IO.__init__(self, filepath)
#------------------------------------------------------------------------------
# [ append method ]
# Universal text file writer that appends to existing file using system default text encoding or utf-8 if throws unicode error
# Tests: test_IO.py:: test_file_ascii_readwrite_append, test_file_append_missingfile
#------------------------------------------------------------------------------
def append(self, text):
try:
from Naked.toolshed.system import file_exists
if not file_exists(self.filepath): #confirm that file exists, if not raise IOError (assuming that developer expected existing file if using append)
raise IOError("The file specified for the text append does not exist (Naked.toolshed.file.py:append).")
with open(self.filepath, 'a') as appender:
appender.write(text)
except UnicodeEncodeError as ue:
self.append_utf8(text) #try writing as utf-8
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to append text to the file with the append() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ append_utf8 method ]
# Text writer that appends text to existing file with utf-8 encoding
# Tests: test_IO.py :: test_file_utf8_readwrite_append
#------------------------------------------------------------------------------
def append_utf8(self, text):
try:
from Naked.toolshed.system import file_exists
if not file_exists(self.filepath):
raise IOError("The file specified for the text append does not exist (Naked.toolshed.file.py:append_utf8).")
import codecs
import unicodedata
norm_text = unicodedata.normalize('NFKD', text) # NKFD normalization of the unicode data before write
with codecs.open(self.filepath, mode='a', encoding="utf_8") as appender:
appender.write(norm_text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to append text to the file with the append_utf8 method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ gzip method (writer) ]
# writes data to gzip compressed file
# Note: adds .gz extension to filename if user did not specify it in the FileWriter class constructor
# Note: uses compresslevel = 6 as default to balance speed and compression level (which in general is not significantly less than 9)
# Tests: test_IO.py :: test_file_gzip_ascii_readwrite, test_file_gzip_utf8_readwrite,
# test_file_gzip_utf8_readwrite_explicit_decode
#------------------------------------------------------------------------------
def gzip(self, text, compression_level=6):
try:
import gzip
if not self.filepath.endswith(".gz"):
self.filepath = self.filepath + ".gz"
with gzip.open(self.filepath, 'wb', compresslevel=compression_level) as gzip_writer:
gzip_writer.write(text)
except UnicodeEncodeError as ue:
import unicodedata
norm_text = unicodedata.normalize('NFKD', text) # NKFD normalization of the unicode data before write
import codecs
binary_data = codecs.encode(norm_text, "utf_8")
with gzip.open(self.filepath, 'wb', compresslevel=compression_level) as gzip_writer:
gzip_writer.write(binary_data)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to gzip compress the file with the gzip method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write method ]
# Universal text file writer that writes by system default or utf-8 encoded unicode if throws UnicdeEncodeError
# Tests: test_IO.py :: test_file_ascii_readwrite, test_file_ascii_readwrite_missing_file,
# test_file_utf8_write_raises_unicodeerror
#------------------------------------------------------------------------------
def write(self, text):
try:
with open(self.filepath, 'wt') as writer:
writer.write(text)
except UnicodeEncodeError as ue:
self.write_utf8(text) # attempt to write with utf-8 encoding
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write to requested file with the write() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write_as method ]
# text file writer that uses developer specified text encoding
# Tests: test_IO.py :: test_file_utf8_readas_writeas
#------------------------------------------------------------------------------
def write_as(self, text, the_encoding=""):
try:
if the_encoding == "": #if the developer did not include the encoding type, raise an exception
raise RuntimeError("The text encoding was not specified as an argument to the write_as() method (Naked.toolshed.file.py:write_as).")
import codecs
with codecs.open(self.filepath, encoding=the_encoding, mode='w') as f:
f.write(text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to write file with the specified encoding using the write_as() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write_bin method ]
# binary data file writer
# Tests: test_IO.py :: test_file_bin_readwrite
#------------------------------------------------------------------------------
def write_bin(self, binary_data):
try:
with open(self.filepath, 'wb') as bin_writer:
bin_writer.write(binary_data)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write binary data to file with the write_bin method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ safe_write method ] (boolean)
# Universal text file writer (writes in default encoding unless throws unicode error) that will NOT overwrite existing file at the requested filepath
# returns boolean indicator for success of write based upon test for existence of file (False = write failed because file exists)
# Tests: test_IO.py :: test_file_ascii_safewrite, test_file_utf8_safewrite
#------------------------------------------------------------------------------
def safe_write(self, text):
import os.path
if not os.path.exists(self.filepath): # if the file does not exist, then can write
try:
with open(self.filepath, 'wt') as writer:
writer.write(text)
return True
except UnicodeEncodeError as ue:
self.write_utf8(text)
return True
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write to requested file with the safe_write() method (Naked.toolshed.file.py).")
raise e
else:
return False # if file exists, do not write and return False
#------------------------------------------------------------------------------
# [ safe_write_bin method ]
# Binary data file writer that will NOT overwrite existing file at the requested filepath
# returns boolean indicator for success of write based upon test for existence of file (False = write failed because file exists)
#------------------------------------------------------------------------------
def safe_write_bin(self, file_data):
try:
import os.path
if not os.path.exists(self.filepath):
with open(self.filepath, 'wb') as writer:
writer.write(file_data)
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write to requested file with the safe_write_bin() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ write_utf8 method ]
# Text file writer with explicit UTF-8 text encoding
# uses filepath from class constructor
# requires text to passed as a method parameter
# Tests: test_IO.py :: test_file_utf8_readwrite, test_file_utf8_readwrite_raises_unicodeerror
#------------------------------------------------------------------------------
def write_utf8(self, text):
try:
import codecs
f = codecs.open(self.filepath, encoding='utf_8', mode='w')
except IOError as ioe:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to open file for write with the write_utf8() method (Naked.toolshed.file.py).")
raise ioe
try:
import unicodedata
norm_text = unicodedata.normalize('NFKD', text) # NKFD normalization of the unicode data before write
f.write(norm_text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to write UTF-8 encoded text to file with the write_utf8() method (Naked.toolshed.file.py).")
raise e
finally:
f.close()
#------------------------------------------------------------------------------
# [ FileReader class ]
# reads data from local files
# filename assigned in constructor (inherited from IO class interface)
#------------------------------------------------------------------------------
class FileReader(IO):
def __init__(self, filepath):
IO.__init__(self, filepath)
#------------------------------------------------------------------------------
# [ read method ] (string)
# Universal text file reader that will read utf-8 encoded unicode or non-unicode text as utf-8
# returns string or unicode (py3 = string for unicode and non-unicode, py2 = str for non-unicode, unicode for unicode)
# Tests: test_IO.py :: test_file_ascii_readwrite, test_file_read_missing_file,
#------------------------------------------------------------------------------
def read(self):
try:
return self.read_utf8() #reads everything as unicode in utf8 encoding
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read text from the requested file with the read() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ read_bin method ] (binary byte string)
# Universal binary data file reader
# returns file contents in binary mode as binary byte strings
# Tests: test_IO.py :: test_file_bin_readwrite, test_file_read_bin_missing_file
#------------------------------------------------------------------------------
def read_bin(self):
try:
with open(self.filepath, 'rb') as bin_reader:
data = bin_reader.read()
return data
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read the binary data from the file with the read_bin method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ read_as method ] (string with developer specified text encoding)
# Text file reader with developer specified text encoding
# returns file contents in developer specified text encoding
# Tests: test_IO.py :: test_file_utf8_readas_writeas, test_file_readas_missing_file
#------------------------------------------------------------------------------
def read_as(self, the_encoding):
try:
if the_encoding == "":
raise RuntimeError("The text file encoding was not specified as an argument to the read_as method (Naked.toolshed.file.py:read_as).")
import codecs
with codecs.open(self.filepath, encoding=the_encoding, mode='r') as f:
data = f.read()
return data
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read the file with the developer specified text encoding with the read_as method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ readlines method ] (list of strings)
# Read text from file line by line, uses utf8 encoding by default
# returns list of utf8 encoded file lines as strings
# Tests: test_IO.py :: test_file_readlines, test_file_readlines_missing_file
#------------------------------------------------------------------------------
def readlines(self):
try:
return self.readlines_utf8() # read as utf8 encoded file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read text from the requested file with the readlines() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ readlines_as method ] (list of developer specified encoded strings)
# Read lines from file with developer specified text encoding
# Returns a list of developer specified encoded lines from the file
# Tests: test_IO.py ::
#------------------------------------------------------------------------------
def readlines_as(self, dev_spec_encoding):
try:
if dev_spec_encoding == "":
raise RuntimeError("The text file encoding was not specified as an argument to the readlines_as method (Naked.toolshed.file.py:readlines_as).")
import codecs
with codecs.open(self.filepath, encoding=dev_spec_encoding, mode='r') as reader:
data_list = []
for line in reader:
data_list.append(line)
return data_list
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to read lines in the specified encoding with the readlines_as method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ readlines_utf8 method ] (list of utf-8 encoded strings)
# Read text from unicode file by line
# Returns list of file unicode text lines as unicode strings
# Tests: test_IO.py :: test_file_readlines_unicode, test_file_readlines_utf8_missing_file
#------------------------------------------------------------------------------
def readlines_utf8(self):
try:
import codecs
with codecs.open(self.filepath, encoding='utf-8', mode='r') as uni_reader:
modified_text_list = []
for line in uni_reader:
import unicodedata
norm_line = unicodedata.normalize('NFKD', line) # NKFD normalization of the unicode data before use
modified_text_list.append(norm_line)
return modified_text_list
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to read lines in the unicode file with the readlines_utf8 method (Naked.toolshed.file.py)")
raise e
#------------------------------------------------------------------------------
# [ read_gzip ] (byte string)
# reads data from a gzip compressed file
# returns the decompressed binary data from the file
# Note: if decompressing unicode file, set encoding="utf-8"
# Tests: test_IO.py :: test_file_gzip_ascii_readwrite, test_file_gzip_utf8_readwrite,
# test_file_read_gzip_missing_file
#------------------------------------------------------------------------------
def read_gzip(self, encoding="system_default"):
try:
import gzip
with gzip.open(self.filepath, 'rb') as gzip_reader:
file_data = gzip_reader.read()
if encoding in ["utf-8", "utf8", "utf_8", "UTF-8", "UTF8", "UTF_8"]:
import codecs
file_data = codecs.decode(file_data, "utf-8")
import unicodedata
norm_data = unicodedata.normalize('NFKD', file_data) # NKFD normalization of the unicode data before passing back to the caller
return norm_data
else:
return file_data
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read from the gzip compressed file with the read_gzip() method (Naked.toolshed.file.py).")
raise e
#------------------------------------------------------------------------------
# [ read_utf8 method ] (string)
# read data from a file with explicit UTF-8 encoding
# uses filepath from class constructor
# returns a unicode string containing the file data (unicode in py2, str in py3)
# Tests: test_IO.py :: test_file_utf8_readwrite, test_file_utf8_readwrite_append,
# test_file_read_utf8_missing_file
#------------------------------------------------------------------------------
def read_utf8(self):
try:
import codecs
f = codecs.open(self.filepath, encoding='utf_8', mode='r')
except IOError as ioe:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to open file for read with read_utf8() method (Naked.toolshed.file.py).")
raise ioe
try:
textstring = f.read()
import unicodedata
norm_text = unicodedata.normalize('NFKD', textstring) # NKFD normalization of the unicode data before returns
return norm_text
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to read the file with UTF-8 encoding using the read_utf8() method (Naked.toolshed.file.py).")
raise e
finally:
f.close()
if __name__ == '__main__':
pass

@ -0,0 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
if __name__ == '__main__':
pass

@ -0,0 +1,105 @@
#!/usr/bin/env python
# encoding: utf-8
#------------------------------------------------------------------------------
# The Ink Templating System
# A lightweight, fast, flexible text templating system
# Copyright 2014 Christopher Simpkins
# MIT License
#------------------------------------------------------------------------------
import re
#------------------------------------------------------------------------------
# Template class
# A template string class that is inherited from Python str
# Includes metadata about the template:
# odel = opening delimiter
# cdel = closing delimiter
# varlist = inclusive list of all variables in the template text (parsed in constructor)
# Delimiters:
# default = {{variable}}
# assign new opening and closing delimiters as parameters when you make a new Template instance
# `escape_regex` boolean is a speedup, avoids Python escape of special regex chars if you do not need it
#------------------------------------------------------------------------------
class Template(str):
def __new__(cls, template_text, open_delimiter="{{", close_delimiter="}}", escape_regex=False):
obj = str.__new__(cls, template_text)
obj.odel = open_delimiter
obj.cdel = close_delimiter
obj.varlist = obj._make_var_list(template_text, escape_regex) #contains all unique parsed variables from the template in a list
return obj
#------------------------------------------------------------------------------
# [ _make_var_list method ] (list of strings)
# Private method that parses the template string for all variables that match the delimiter pattern
# Returns a list of the variable names as strings
#------------------------------------------------------------------------------
def _make_var_list(self, template_text, escape_regex=False):
if escape_regex:
open_match_pat = self._escape_regex_special_chars(self.odel)
close_match_pat = self._escape_regex_special_chars(self.cdel)
match_pat = open_match_pat + r'(.*?)' + close_match_pat # capture group contains the variable name used between the opening and closing delimiters
else:
match_pat = self.odel + r'(.*?)' + self.cdel
var_list = re.findall(match_pat, template_text) #generate a list that contains the capture group from the matches (i.e. the variables in the template)
return set(var_list) # remove duplicate entries by converting to set (and lookup speed improvement from hashing)
#------------------------------------------------------------------------------
# [ _escape_regex_special_chars method ] (string)
# Private method that escapes special regex metacharacters
# Returns a string with the escaped character modifications
#------------------------------------------------------------------------------
def _escape_regex_special_chars(self, test_escape_string):
return re.escape(test_escape_string)
#------------------------------------------------------------------------------
# Renderer class
# Render the variable replacements in the ink template using a Python dictionary key argument
# Construct the instace of the Renderer with the Ink template and the dictionary key
# Run the renderer with the render method on the instance (e.g. r.render())
# Parameters to constructor:
# - template = an Ink Template instance
# - key = a dictionary mapped key = variable name : value = variable replacement data
# - html_entities = encode html entities with HTML escaped characters (default = False = do not encode)
#------------------------------------------------------------------------------
class Renderer:
def __init__(self, template, key, html_entities=False):
self.odel = template.odel
self.cdel = template.cdel
self.template = template
self.html_entities = html_entities
self.key_dict = key
#------------------------------------------------------------------------------
# [ render method ] (string)
# renders the variable replacements in the Ink template
# returns the rendered template as a string
#------------------------------------------------------------------------------
def render(self):
# make local variables for the loop below (faster)
local_dict = self.key_dict
local_template = self.template
local_varlist = self.template.varlist
local_odel = self.odel
local_cdel = self.cdel
local_htmlent = self.html_entities
if local_htmlent:
from xml.sax.saxutils import escape #from Python std lib
for key in local_dict:
if key in local_varlist:
value = local_dict[key]
replace_string = local_odel + key + local_cdel
if local_htmlent:
value = escape(value) #xml.sax.saxutils function
local_template = local_template.replace(replace_string, value)
return local_template
##TODO : multiple file render method?
if __name__ == '__main__':
pass
# template = Template("This is a of the {{test}} of the {{document}} {{type}} and more of the {{test}} {{document}} {{type}}")
# renderer = Renderer(template, {'test': 'ব য', 'document':'testing document', 'type':'of mine', 'bogus': 'bogus test'})
# print(renderer.render())

@ -0,0 +1,14 @@
#!/usr/bin/env python
# encoding: utf-8
import itertools
#------------------------------------------------------------------------------
# [ chain_iter method ] (iterable items of type contained in multiple list arguments)
# Generator that returns iterable for each item in the multiple list arguments in sequence
#------------------------------------------------------------------------------
def chain_iter(self, *lists):
return itertools.chain(*lists)
if __name__ == '__main__':
pass

@ -0,0 +1,351 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
import requests
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
#[ HTTP class]
# handle HTTP requests
# Uses the requests external library to handle HTTP requests and response object (available on PyPI)
#------------------------------------------------------------------------------
class HTTP():
def __init__(self, url="", request_timeout=10):
self.url = url
self.request_timeout = request_timeout
#------------------------------------------------------------------------------
# HTTP response properties (assignment occurs with the HTTP request methods)
#------------------------------------------------------------------------------
self.res = None # assigned with the requests external library response object after a HTTP method call
#------------------------------------------------------------------------------
# [ get method ] (string) -
# HTTP GET request - returns text string
# returns data stream read from the URL (string)
# Default timeout = 10 s from class constructor
# Re-throws ConnectionError on failed connection (e.g. no site at URL)
# Test : test_NETWORK.py :: test_http_get, test_http_get_response_change,
# test_http_post_reponse_change, test_http_get_response_check
#------------------------------------------------------------------------------
def get(self, follow_redirects=True):
try:
response = requests.get(self.url, timeout=self.request_timeout, allow_redirects=follow_redirects)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.text
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request with the URL " + self.url + " using the get() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ get_data method ] (binary data)
# HTTP GET request, return binary data
# returns data stream with raw binary data
#------------------------------------------------------------------------------
def get_bin(self):
try:
response = requests.get(self.url, timeout=self.request_timeout)
self.res = response # assign the response object from requests to a property on the instance
return response.content # return binary data instead of text (get() returns text)
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request with the URL " + self.url + " using the get_data() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ get_bin_write_file method ] (boolean)
# open HTTP data stream with GET request, make file with the returned binary data
# file path is passed to the method by the developer
# set suppress_output to True if you want to suppress the d/l status information that is printed to the standard output stream
# return True on successful pull and write to disk
# Tests: test_NETWORK.py :: test_http_get_binary
#------------------------------------------------------------------------------
def get_bin_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...")
sys.stdout.flush()
response = requests.get(self.url, timeout=self.request_timeout, stream=True)
self.res = response
with open(filepath, 'wb') as f: # write as binary data
for chunk in response.iter_content(chunk_size=2048):
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.")
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request and write file with the URL " + self.url + " using the get_bin_write_file() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ get_txt_write_file method ] (boolean)
# open HTTP data stream with GET request, write file with utf-8 encoded text using returned text data
# file path is passed to the method by the developer (default is the base filename in the URL if not specified)
# return True on successful pull and write to disk
# Tests: test_NETWORK.py :: test_http_get_text
#------------------------------------------------------------------------------
def get_txt_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...")
sys.stdout.flush()
response = requests.get(self.url, timeout=self.request_timeout, stream=True)
self.res = response
import codecs
with codecs.open(filepath, mode='w', encoding="utf-8") as f: #write as text
for chunk in response.iter_content(chunk_size=2048):
chunk = chunk.decode('utf-8')
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.")
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform GET request and write file with the URL " + self.url + " using the get_data_write_txt() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ head method ] (dictionary of strings)
# HTTP HEAD request
# returns a dictionary of the header strings
# test for a specific header on either the response dictionary or the instance res property
# Usage example:
# content_type = instance.res['content-type']
# Tests: test_NETWORK.py :: test_http_head
#------------------------------------------------------------------------------
def head(self):
try:
response = requests.head(self.url, timeout=self.request_timeout)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.headers
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform a HEAD request with the head() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post method ] (string)
# HTTP POST request for text
# returns text from the URL as a string
#------------------------------------------------------------------------------
def post(self, follow_redirects=True):
try:
response = requests.post(self.url, timeout=self.request_timeout, allow_redirects=follow_redirects)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.text
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.exit("Naked Framework Error: Unable to perform a POST request with the post() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post_bin method ] (binary data)
# HTTP POST request for binary data
# returns binary data from the URL
#------------------------------------------------------------------------------
def post_bin(self):
try:
response = requests.post(self.url, timeout=self.request_timeout)
self.res = response # assign the response object from requests to a property on the instance of HTTP class
return response.content
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.exit("Naked Framework Error: Unable to perform POST request with the post_bin() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post_bin_write_file method ] (boolean = success of write)
# HTTP POST request, write binary file with the response data
# default filepath is the basename of the URL file, may be set by passing an argument to the method
# returns a boolean that indicates the success of the file write
#------------------------------------------------------------------------------
def post_bin_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...") #provide information about the download to user
sys.stdout.flush()
response = requests.post(self.url, timeout=self.request_timeout, stream=True)
self.res = response
with open(filepath, 'wb') as f: # write as binary data
for chunk in response.iter_content(chunk_size=2048):
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.") # provide user with completion information
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform POST request and write file with the URL " + self.url + " using the post_data_write_bin() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ post_txt_write_file method ] (boolean = success of file write)
# HTTP POST request, write utf-8 encoded text file with the response data
# default filepath is the basename of the URL file, may be set by passing an argument to the method
# returns a boolean that indicates the success of the file write
#------------------------------------------------------------------------------
def post_txt_write_file(self, filepath="", suppress_output = False, overwrite_existing = False):
try:
import os # used for os.fsync() method in the write
# Confirm that the file does not exist and prevent overwrite if it does (unless developer indicates otherwise)
if not overwrite_existing:
from Naked.toolshed.system import file_exists
if file_exists(filepath):
if not suppress_output:
print("Download aborted. A local file with the requested filename exists on the path.")
return False
if (filepath == "" and len(self.url) > 1):
filepath = self.url.split('/')[-1] # use the filename from URL and working directory as default if not specified
if not suppress_output:
sys.stdout.write("Downloading file from " + self.url + "...") #provide information about the download to user
sys.stdout.flush()
response = requests.post(self.url, timeout=self.request_timeout, stream=True)
self.res = response
import codecs
with codecs.open(filepath, mode='w', encoding="utf-8") as f: # write as binary data
for chunk in response.iter_content(chunk_size=2048):
chunk = chunk.decode('utf-8')
f.write(chunk)
f.flush()
os.fsync(f.fileno()) # flush all internal buffers to disk
if not suppress_output:
print(" ")
print("Download complete.") # provide user with completion information
return True # return True if successful write
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to perform POST request and write file with the URL " + self.url + " using the post_data_write_bin() method (Naked.toolshed.network.py)")
raise e
#------------------------------------------------------------------------------
# [ response method ]
# getter method for the requests library object that is assigned as a property
# on the HTTP class after a HTTP request method is run (e.g. get())
# Note: must run one of the HTTP request verbs to assign this property before use of getter (=None by default)
# Tests: test_NETWORK.py :: test_http_get_response_check
#------------------------------------------------------------------------------
def response(self):
try:
return self.res
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to return the response from your HTTP request with the response() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ get_status_ok method ] (boolean)
# return boolean whether HTTP response was in 200 status code range for GET request
# Note: this method runs its own GET request, does not need to be run separately
# Tests: test_NETWORK.py ::
#------------------------------------------------------------------------------
def get_status_ok(self):
try:
self.get() #run the get request
if self.res and self.res.status_code:
return (self.res.status_code == requests.codes.ok)
else:
return False
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to obtain the HTTP status with the get_status_ok() method (Naked.toolshed.network.py).")
raise e
#------------------------------------------------------------------------------
# [ post_status_ok method ] (boolean)
# return boolean whether HTTP response was in 200 status code range for POST request
# Note: method runs its own post method, not necessary to run separately
#------------------------------------------------------------------------------
def post_status_ok(self):
try:
self.post() #run the post request
if self.res and self.res.status_code:
return (self.res.status_code == requests.codes.ok)
else:
return False
except requests.exceptions.ConnectionError as ce:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Unable to obtain the HTTP status with the post_status_ok() method (Naked.toolshed.network.py).")
raise e
if __name__ == '__main__':
pass
#------------------------------------------------------------------------------
# HTTP GET 1
#------------------------------------------------------------------------------
# http = HTTP("http://www.google.com")
# data = http.get()
# print(data)
# from Naked.toolshed.file import FileWriter
# w = FileWriter("testfile.txt")
# w.write_utf8(data)
#------------------------------------------------------------------------------
# HTTP GET 2
#------------------------------------------------------------------------------
# http = HTTP()
# http.url = "http://www.google.com"
# print(http.get())

@ -0,0 +1,53 @@
#!/usr/bin/env python
# encoding: utf-8
# tests: test_PYTHON.py
from sys import version_info
#------------------------------------------------------------------------------
# Python Versions
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ py_version function ] (tuple of (major, minor, patch))
#------------------------------------------------------------------------------
def py_version():
return (version_info[0], version_info[1], version_info[2])
#------------------------------------------------------------------------------
# [ py_major_version function ] (integer)
# Return Python interpreter major version number
#------------------------------------------------------------------------------
def py_major_version():
return (version_info[0])
#------------------------------------------------------------------------------
# [ py_minor_version function ] (integer)
# Return Python interpreter minor version number
#------------------------------------------------------------------------------
def py_minor_version():
return (version_info[1])
#------------------------------------------------------------------------------
# [ py_patch_version function ] (integer)
# Return Python interpreter patch version number
#------------------------------------------------------------------------------
def py_patch_version():
return (version_info[2])
#------------------------------------------------------------------------------
# [ is_py2 function ] (boolean)
# Return truth result for question is interpreter running a version of Python 2
#------------------------------------------------------------------------------
def is_py2():
return (version_info[0] == (2))
#------------------------------------------------------------------------------
# [ is_py3 function ] (boolean)
# Return truth result for question is interpreter running a version of Python 3
#------------------------------------------------------------------------------
def is_py3():
return (version_info[0] == (3))
if __name__ == '__main__':
pass

@ -0,0 +1,263 @@
#!/usr/bin/env python
# encoding: utf-8
import os
import sys
import subprocess
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [ execute function ] (boolean)
# run a shell command and print std out / std err to terminal
# returns True if exit status = 0
# returns False if exit status != 0
#------------------------------------------------------------------------------
def execute(command):
try:
response = subprocess.call(command, shell=True)
if response == 0:
return True
else:
return False
except subprocess.CalledProcessError as cpe:
try:
sys.stderr.write(cpe.output)
except TypeError as te:
sys.stderr.write(str(cpe.output))
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the execute() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ run function ] (bytes string or False)
# run a shell command
# default =
# success:: print to std out and return the std out string
# error:: print to stderr return False, suppress SystemExit on error to permit ongoing run of calling script
# suppress_stdout = True >> suppress std output stream print (returns string)
# suppress_stderr = True >> suppress std err stream print (returns False)
# suppress_exit_status_call = False >> raise SystemExit with the returned status code
#------------------------------------------------------------------------------
def run(command, suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
try:
response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
if not suppress_stdout:
print(response)
return response
except subprocess.CalledProcessError as cpe:
if not suppress_stderr: # error in existing application (non-zero exit status)
try:
sys.stderr.write(cpe.output)
except TypeError as te: # deal with unusual errors from some system executables that return non string type through subprocess.check_output
sys.stderr.write(str(cpe.output))
if not suppress_exit_status_call:
if cpe.returncode:
sys.exit(cpe.returncode)
else:
sys.exit(1)
return False # return False on non-zero exit status codes (i.e. failures in the subprocess executable)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ muterun function ] (NakedObject with attributes for stdout, stderr, exitcode)
# run a shell command and return a response object
# return object attributes : stdout (bytes), stderr (bytes), exitcode (int)
#------------------------------------------------------------------------------
def muterun(command):
try:
from Naked.toolshed.types import NakedObject
response_obj = NakedObject()
response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
response_obj.stdout = response
response_obj.exitcode = 0
response_obj.stderr = b""
return response_obj
except subprocess.CalledProcessError as cpe:
response_obj.stdout = b""
response_obj.stderr = cpe.output
if cpe.returncode:
response_obj.exitcode = cpe.returncode
else:
response_obj.exitcode = 1
return response_obj
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the mute_run() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# RUBY COMMAND EXECUTION
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ execute_rb function ] (boolean)
# execute a ruby script file in a shell subprocess
#------------------------------------------------------------------------------
def execute_rb(file_path, arguments=""):
try:
if len(arguments) > 0:
rb_command = 'ruby ' + file_path + " " + arguments
else:
rb_command = 'ruby ' + file_path
return execute(rb_command) # return result of execute() of the ruby file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_rb() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ run_rb function ] (bytes string or False)
# execute a ruby script file in a shell subprocess, return the output
#------------------------------------------------------------------------------
def run_rb(file_path, arguments="", suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
try:
if len(arguments) > 0:
rb_command = 'ruby ' + file_path + " " + arguments
else:
rb_command = 'ruby ' + file_path
return run(rb_command, suppress_stdout, suppress_stderr, suppress_exit_status_call) # return result of run() of the ruby file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_rb() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ muterun_rb function ] (NakedObject response object)
#------------------------------------------------------------------------------
def muterun_rb(file_path, arguments=""):
try:
if len(arguments) > 0:
rb_command = 'ruby ' + file_path + " " + arguments
else:
rb_command = 'ruby ' + file_path
return muterun(rb_command) # return result of muterun() of the ruby file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the muterun_rb() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# NODE.JS COMMAND EXECUTION
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ execute_js function ] (boolean)
# execute a node.js script file in a shell subprocess
# stdout stream to terminal
# returns True for success (=0) exit status code
# returns False for unsuccessful (!=0) exit status code
#------------------------------------------------------------------------------
def execute_js(file_path, arguments=""):
try:
if len(arguments) > 0:
js_command = 'node ' + file_path + " " + arguments
else:
js_command = 'node ' + file_path
return execute(js_command) # return result of execute() of node.js file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_js() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ run_js function ] (byte string or False)
# execute a node.js script file in a shell subprocess
# print the standard output to the standard output stream by default
# set suppress_output to True to suppress stream to standard output. String is still returned to calling function
# set suppress_exit_status_call to True to suppress raising sys.exit on failures with shell subprocess exit status code (if available) or 1 if not available
# returns the standard output byte string from the subprocess executable on success
# returns False if the subprocess exits with a non-zero exit code
#------------------------------------------------------------------------------
def run_js(file_path, arguments="", suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
try:
if len(arguments) > 0:
js_command = 'node ' + file_path + " " + arguments
else:
js_command = 'node ' + file_path
return run(js_command, suppress_stdout, suppress_stderr, suppress_exit_status_call) # return result of run() of node.js file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_js() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ muterun_js function ] (NakedObject response object)
#------------------------------------------------------------------------------
def muterun_js(file_path, arguments=""):
try:
if len(arguments) > 0:
js_command = 'node ' + file_path + " " + arguments
else:
js_command = 'node ' + file_path
return muterun(js_command) # return result of muterun() of node.js file
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to run the shell command with the muterun_js() function (Naked.toolshed.shell.py).")
raise e
#------------------------------------------------------------------------------
# [ Environment Class ]
# shell environment variables class
# self.env = the environment variable dictionary
# self.vars = the environment variable names list
#------------------------------------------------------------------------------
class Environment():
def __init__(self):
self.env = os.environ
self.vars = list(os.environ.keys())
#------------------------------------------------------------------------------
# [ is_var method ] (boolean)
# return boolean for presence of a variable name in the shell environment
#------------------------------------------------------------------------------
def is_var(self, var_name):
try:
return (var_name in self.vars)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to determine if the variable is included in the shell variable list with the is_var() method (Naked.toolshed.shell).")
raise e
#------------------------------------------------------------------------------
# [ get_var method ] (string)
# get the variable value for a variable in the shell environment list
# returns empty string if the variable is not included in the environment variable list
#------------------------------------------------------------------------------
def get_var(self, var_name):
try:
if var_name in self.vars:
return self.env[var_name]
else:
return ""
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return the requested shell variable with the get_var() method (Naked.toolshed.shell).")
raise e
#------------------------------------------------------------------------------
# [ get_split_var_list method ] (list of strings)
# return a list of strings split by OS dependent separator from the shell variable assigment string
# if the variable name is not in the environment list, returns an empty list
#------------------------------------------------------------------------------
def get_split_var_list(self, var_name):
try:
if var_name in self.vars:
return self.env[var_name].split(os.pathsep)
else:
return []
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return environment variable list with the get_split_var_list() method (Naked.toolshed.shell).")
raise e
if __name__ == '__main__':
pass
# e = Environment()
# pathlist = e.get_split_var_list("PATH")
# for item in pathlist:
# print(item)

@ -0,0 +1,34 @@
#!/usr/bin/env python
# encoding: utf-8
from Naked.settings import debug as DEBUG_FLAG
from Naked.toolshed.system import cwd
import Naked.toolshed.python as py
import sys
import os
import datetime
class StateObject:
def __init__(self):
now = datetime.datetime.now()
self.py2 = py.is_py2() #truth test Python 2 interpreter
self.py3 = py.is_py3() #truth test Python 3 interpreter
self.py_major = py.py_major_version() #Python major version
self.py_minor = py.py_minor_version() #Python minor version
self.py_patch = py.py_patch_version() #Python patch version
self.os = sys.platform #user operating system
self.cwd = cwd() #current (present) working directory
self.parent_dir = os.pardir
self.default_path = os.defpath
self.user_path = os.path.expanduser("~")
self.string_encoding = sys.getdefaultencoding()
self.file_encoding = sys.getfilesystemencoding()
self.hour = now.hour
self.min = now.minute
self.year = now.year
self.day = now.day
self.month = now.month
self.second = now.second
if __name__ == '__main__':
pass

@ -0,0 +1,553 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
import os
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
#
# FILE & DIRECTORY PATHS
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ filename function ] (string)
# returns file name from a file path (including the file extension)
# Tests: test_SYSTEM.py :: test_sys_filename
#------------------------------------------------------------------------------
def filename(filepath):
try:
return os.path.basename(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return base filename from filename() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ file_extension function ] (string)
# returns file extension from a filepath
# Tests: test_SYSTEM.py :: test_sys_file_extension
#------------------------------------------------------------------------------
def file_extension(filepath):
try:
return os.path.splitext(filepath)[1]
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return file extension with file_extension() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ directory function ] (string)
# returns directory path to the filepath
# Tests: test_SYSTEM.py :: test_sys_dir_path
#------------------------------------------------------------------------------
def directory(filepath):
try:
return os.path.dirname(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return directory path to file with directory() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ make_path function ] (string)
# returns OS independent file path from tuple of path components
# Tests: test_SYSTEM.py :: test_sys_make_filepath
#------------------------------------------------------------------------------
def make_path(*path_list):
try:
return os.path.join(*path_list)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to make OS independent path with the make_path() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ currentdir_to_basefile decorator function ] (returns decorated original function)
# concatenates the absolute working directory path to the basename of file in the first parameter of the undecorated function
# Tests: test_SYSTEM.py :: test_sys_add_currentdir_path_to_basefile
#------------------------------------------------------------------------------
def currentdir_to_basefile(func):
try:
from functools import wraps
@wraps(func)
def wrapper(file_name, *args, **kwargs):
current_directory = os.getcwd() #get current working directory path
full_path = os.path.join(current_directory, file_name) # join cwd path to the filename for full path
return func(full_path, *args, **kwargs) #return the original function with the full path to file as first argument
return wrapper
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with the currentdir_to_basefile() decorator function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ currentdir_firstparam decorator function ] (returns decorated original function)
# adds the current working directory as the first function parameter of the decorated function
# Tests: test_SYSTEM.py :: test_sys_add_currentdir_path_first_arg
#------------------------------------------------------------------------------
def currentdir_firstparam(func):
try:
from functools import wraps
@wraps(func)
def wrapper(dir="", *args, **kwargs):
current_directory = os.getcwd()
return func(current_directory, *args, **kwargs)
return wrapper
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with the currentdir_firstargument() decorator function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ currentdir_lastargument decorator function ] (returns decorated original function)
# adds the current working directory as the last function parameter of the decorated function
# Note: you cannot use other named arguments in the original function with this decorator
# Note: the current directory argument in the last position must be named current_dir
# Tests: test_SYSTEM.py :: test_sys_add_currentdir_last_arg
#------------------------------------------------------------------------------
def currentdir_lastparam(func):
try:
from functools import wraps
@wraps(func)
def wrapper(*args, **kwargs):
the_cwd = os.getcwd()
return func(*args, current_dir=the_cwd)
return wrapper
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with the currentdir_lastargument() decorator function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ fullpath function ] (string)
# returns the absolute path to a file that is in the current working directory
# file_name = the basename of the file in the current working directory
# Example usage where test.txt is in working directory:
# filepath = fullpath("test.txt")
# Tests: test_SYSTEM.py :: test_sys_full_path_to_file
#------------------------------------------------------------------------------
@currentdir_to_basefile # current directory decorator - adds the directory path up to the filename to the basefile name argument to original function
def fullpath(file_name):
try:
return file_name
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return absolute path to the file with the fullpath() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ cwd function ] (string)
# returns the current working directory path
# does not need to be called with an argument, the decorator assigns it
# Example usage:
# current_dir = cwd()
# Tests: test_SYSTEM.py :: test_sys_cwd_path
#------------------------------------------------------------------------------
@currentdir_firstparam
def cwd(dir=""):
try:
return dir
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return the current working directory with the cwd() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# DIRECTORY WRITES
#
#------------------------------------------------------------------------------
## TODO: add tests
#------------------------------------------------------------------------------
# [ make_dirs function ] (--none--)
# make a new directory path (recursive if multiple levels of depth) if it
# DOES NOT already exist
#------------------------------------------------------------------------------
def make_dirs(dirpath):
try:
import os
import errno
os.makedirs(dirpath)
return True
except OSError as ose:
if ose.errno != errno.EEXIST: # directory already exists
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: Could not write the directory path passed as an argument to the make_dirs() function (Naked.toolshed.system).")
raise ose
else:
return False
except Exception as e:
raise e
#------------------------------------------------------------------------------
#
# FILE & DIRECTORY TESTING
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ file_exists function ] (boolean)
# return boolean for existence of file in specified path
# Tests: test_SYSTEM.py :: test_file_exists
#------------------------------------------------------------------------------
def file_exists(filepath):
try:
if os.path.exists(filepath) and os.path.isfile(filepath): # test that exists and is a file
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for the presence of the file with the file_exists() method (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ is_file function ] (boolean)
# returns boolean for determination of whether filepath is a file
# Tests: test_SYSTEM.py :: test_sys_is_file, test_sys_is_file_missing_file,
# test_sys_is_file_when_dir
#------------------------------------------------------------------------------
def is_file(filepath):
try:
return os.path.isfile(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for file with the is_file() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ dir_exists function ] (boolean)
# return boolean for existence of directory in specified path
# Tests: test_SYSTEM.py :: test_dir_exists, test_dir_exists_missing_dir
#------------------------------------------------------------------------------
def dir_exists(dirpath):
try:
if os.path.exists(dirpath) and os.path.isdir(dirpath): # test that exists and is a directory
return True
else:
return False
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for directory with the dir_exists() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ is_dir function ] (boolean)
# returns boolean for determination of whether dirpath is a directory
# Tests: test_SYSTEM.py :: test_sys_dir_is_dir, test_sys_dir_is_dir_when_file,
# test_sys_dir_is_dir_when_missing
#------------------------------------------------------------------------------
def is_dir(dirpath):
try:
return os.path.isdir(dirpath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: error with test for directory with the is_dir() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# FILE METADATA
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ filesize function ] (int)
# return file size in bytes
# Tests: test_SYSTEM.py :: test_sys_meta_file_size
#------------------------------------------------------------------------------
def file_size(filepath):
try:
return os.path.getsize(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return file size with the file_size() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ file_mod_time function ] (string)
# return the last file modification date/time
# Tests: test_SYSTEM.py :: test_sys_meta_file_mod
#------------------------------------------------------------------------------
def file_mod_time(filepath):
try:
import time
return time.ctime(os.path.getmtime(filepath))
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return file modification data with the file_mod_time() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# FILE LISTINGS
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ list_all_files function ] (list)
# returns a list of all files in developer specified directory
# Tests: test_SYSTEM.py :: test_sys_list_all_files, test_sys_list_all_files_emptydir
#------------------------------------------------------------------------------
def list_all_files(dir):
try:
filenames = [name for name in os.listdir(dir) if os.path.isfile(os.path.join(dir, name))]
return filenames
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to generate directory file list with the list_all_files() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_filter_files function ] (list)
# returns a list of files filtered by developer defined file extension in developer defined directory
# Usage example:
# filenames = list_filter_files("py", "tests")
# Tests: test_SYSTEM.py :: test_sys_list_filter_files, test_sys_list_filter_files_nomatch
#------------------------------------------------------------------------------
def list_filter_files(extension_filter, dir):
try:
if not extension_filter.startswith("."):
extension_filter = "." + extension_filter
filenames = [name for name in os.listdir(dir) if name.endswith(extension_filter)]
return filenames
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of filtered files with the list_filter_files() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_all_files_cwd function ] (list)
# returns a list of all files in the current working directory
# Note: does not require argument, the decorator assigns the cwd
# Usage example:
# file_list = list_all_files_cwd()
# Tests: test_SYSTEM.py :: test_sys_list_all_files_cwd
#------------------------------------------------------------------------------
@currentdir_firstparam
def list_all_files_cwd(dir=""):
try:
return list_all_files(dir)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of all files in current working directory with the list_all_files_cwd() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_filter_files_cwd function ] (list)
# returns a list of all files in the current working directory filtered by developer specified file extension
# Note: do not specify the second argument, decorator assigns it
# Usage example:
# file_list = list_filter_files_cwd(".py")
# Tests: test_SYSTEM.py :: test_sys_filter_files_cwd, test_sys_filter_files_cwd_nomatch
#------------------------------------------------------------------------------
@currentdir_lastparam
def list_filter_files_cwd(extension_filter, current_dir=""):
try:
return list_filter_files(extension_filter, current_dir)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of filtered files in current working directory with the list_filter_files_cwd() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ list_match_files function ] (list)
# returns a list of all files that match the developer specified wildcard match pattern
# can optionally specify return of full path to the files (rather than relative path from cwd) by setting full_path to True
# Usage examples:
# file_list = list_match_files("*.py")
# file_list_fullpath = list_match_files("*.py", True)
# Tests: test_SYSTEM.py :: test_sys_match_files, test_sys_match_files_fullpath
#------------------------------------------------------------------------------
def list_match_files(match_pattern, full_path = False):
try:
from glob import glob
filenames = glob(match_pattern)
if full_path:
filenames_fullpath = []
cwd = os.getcwd()
for name in filenames:
name = os.path.join(cwd, name) #make the full path to the file
filenames_fullpath.append(name) #add to the new list
return filenames_fullpath #then return that list
else:
return filenames
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return list of matched files with the list_match_files() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# SYMBOLIC LINK TESTING
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ is_link function ] (boolean)
# return boolean indicating whether the path is a symbolic link
#------------------------------------------------------------------------------
def is_link(filepath):
try:
return os.path.islink(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to determine whether path is a symbolic link with the is_link() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ real_path function ] (string)
# return the real file path pointed to by a symbolic link
#------------------------------------------------------------------------------
def real_path(filepath):
try:
return os.path.realpath(filepath)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to return real path for symbolic link with the real_path() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# DATA STREAMS
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ stdout function ]
# print to std output stream
#------------------------------------------------------------------------------
def stdout(text):
try:
print(text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stdout_xnl function ]
# print to std output stream without a newline
#------------------------------------------------------------------------------
def stdout_xnl(text):
try:
sys.stdout.write(text)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_xnl() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stdout_iter function ]
# print items in an iterable to the standard output stream with newlines after each string
#------------------------------------------------------------------------------
def stdout_iter(iter):
try:
for x in iter:
stdout(x)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_iter() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stdout_iter_xnl function ]
# print items in an iterable to the standard output stream without newlines after each string
#------------------------------------------------------------------------------
def stdout_iter_xnl(iter):
try:
for x in iter:
stdout_xnl(x)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_iter() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stderr function ]
# print to std error stream
# optionally (i.e. if exit = nonzero integer) permits exit from application with developer defined exit code
#------------------------------------------------------------------------------
def stderr(text, exit=0):
try:
sys.stderr.write(text + "\n")
if exit:
raise SystemExit(exit)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard error stream with the stderr() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
# [ stderr_xnl function ]
# print to the standard error stream without a newline character after the `text` string
#------------------------------------------------------------------------------
def stderr_xnl(text, exit=0):
try:
sys.stderr.write(text)
if exit:
raise SystemExit(exit)
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to print to the standard error stream with the stderr() function (Naked.toolshed.system).")
raise e
#------------------------------------------------------------------------------
#
# APPLICATION CONTROL
#
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ exit_with_status function ]
# application exit with developer specified exit status code (default = 0)
# use an exit status integer argument
# Tests: test_SYSTEM.py :: test_sys_exit_with_code
#------------------------------------------------------------------------------
def exit_with_status(exit=0):
raise SystemExit(exit)
#------------------------------------------------------------------------------
# [ exit_fail function ]
# application exit with status code 1
# Tests: test_SYSTEM.py :: test_sys_exit_failure
#------------------------------------------------------------------------------
def exit_fail():
raise SystemExit(1)
#------------------------------------------------------------------------------
# [ exit_success function]
# application exit with status code 0
# Tests: test_SYSTEM.py :: test_sys_exit_success
#------------------------------------------------------------------------------
def exit_success():
raise SystemExit(0)
if __name__ == '__main__':
pass
# #------------------------------------------------------------------------------
# # Standard Output Tests
# #------------------------------------------------------------------------------
# stdout("This is a test")
# for x in range(10):
# stdout_xnl(str(x) + " ")
# list_ten = ['10% ', '20% ', '30% ', '40% ', '50% ', '60% ', '70% ', '80% ', '90% ', '100%']
# stdout_iter(list_ten)
# #------------------------------------------------------------------------------
# # Standard Error Tests
# #------------------------------------------------------------------------------
# stderr("This is a test")
# stderr("This is a test", 1) #exit with status code 1

@ -0,0 +1,992 @@
#!/usr/bin/env python
# encoding: utf-8
import sys
from Naked.settings import debug as DEBUG_FLAG
#------------------------------------------------------------------------------
# [[ NakedObject class ]]
# A generic Python object
# Assigns object attributes by key name in the dictionary argument to the constructor
# The methods are inherited by other mutable Naked object extension types
# Attribute accessors: hasattr, getattr, setattr, delattr
#------------------------------------------------------------------------------
class NakedObject(object):
# initialize with an attributes dictionary {attribute_name: attribute_value}
def __init__(self, attributes={}, naked_type='NakedObject'):
if len(attributes) > 0:
for key in attributes:
setattr(self, key, attributes[key])
setattr(self, '_naked_type_', naked_type) # maintain an attribute to keep track of the extension type
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the NakedObject instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ _equal_type method ] (boolean)
# returns boolean for type of instance == type of test parameter instance
#------------------------------------------------------------------------------
def _equal_type(self, other_obj):
return type(self) == type(other_obj)
#------------------------------------------------------------------------------
# [ _equal_attributes metod ] (method)
# returns boolean for instance.__dict__ == test parameter .__dict__ (attribute comparison)
#------------------------------------------------------------------------------
def _equal_attributes(self, other_obj):
return self.__dict__ == other_obj.__dict__
#------------------------------------------------------------------------------
# == overload
#------------------------------------------------------------------------------
def __eq__(self, other_obj):
return self.equals(other_obj)
#------------------------------------------------------------------------------
# != overload
#------------------------------------------------------------------------------
def __ne__(self, other_obj):
result = self.equals(other_obj)
if result:
return False # reverse result of the equals method
else:
return True
#------------------------------------------------------------------------------
# [ equals method ] (boolean)
# equality testing based on type and attributes
# **NEED TO OVERRIDE IN CLASSES THAT INHERIT
#------------------------------------------------------------------------------
def equals(self, other_obj):
return self._equal_type(other_obj) and self._equal_attributes(other_obj)
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
#------------------------------------------------------------------------------
# [[ XDict class ]]
# An inherited extension to the dictionary type
#------------------------------------------------------------------------------
class XDict(dict, NakedObject):
def __init__(self, dict_obj, attributes={}, naked_type='XDict'):
dict.__init__(self, dict_obj)
NakedObject.__init__(self, attributes, naked_type)
#------------------------------------------------------------------------------
# XDict Operator Overloads
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# + overload
# overwrites existing keys with key:value pairs from new dictionaries if they are the same keys
# returns the updated XDict object
#------------------------------------------------------------------------------
def __add__(self, other_dict):
try:
self.update(other_dict)
if hasattr(other_dict, '_naked_type_') and (getattr(other_dict, '_naked_type_') == 'XDict'):
attr_dict = other_dict._getAttributeDict() # get the attributes from the parameter XDict and add to new XDict
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XDict with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# +- overload
# overwrites existing keys with another_dict (right sided argument) keys if they are the same keys
# returns the updated XDict object
#------------------------------------------------------------------------------
def __iadd__(self, other_dict):
try:
self.update(other_dict)
if hasattr(other_dict, '_naked_type_') and (getattr(other_dict, '_naked_type_') == 'XDict'):
attr_dict = other_dict._getAttributeDict() # get the attributes from the parameter XDict and add to new XDict
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XDict with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# == overload
#------------------------------------------------------------------------------
def __eq__(self, other_obj):
return self.equals(other_obj)
#------------------------------------------------------------------------------
# != overload
#------------------------------------------------------------------------------
def __ne__(self, other_obj):
result = self.equals(other_obj)
if result:
return False # reverse result of the equals method
else:
return True
#------------------------------------------------------------------------------
# [ equals method ] (boolean)
# tests for equality of the XDict (type, attributes, dictionary equality)
#------------------------------------------------------------------------------
def equals(self, other_obj):
if self._equal_type(other_obj) and self._equal_attributes(other_obj):
if dict(self) == dict(other_obj):
return True
else:
return False
else:
return False
#------------------------------------------------------------------------------
# XDict Value Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ conditional_map_to_vals method ] (XDict)
# returns the original XDict with values that meet True condition in `conditional_function`
# modified as per the `mapped_function` with single value argument call
# Test: test_xdict_conditional_map
#------------------------------------------------------------------------------
def conditional_map_to_vals(self, conditional_function, mapped_function):
for key, value in self.xitems():
if conditional_function(key):
self[key] = mapped_function(value)
return self
#------------------------------------------------------------------------------
# [ map_to_vals method ] (XDict)
# returns the original XDict with all values modified as per the `mapped_function`
# Test: test_xdict_map_to_vals
#------------------------------------------------------------------------------
def map_to_vals(self, mapped_function):
# return XDict( zip(self, map(mapped_function, self.values())), self._getAttributeDict() ) - slower in Py2
for key, value in self.xitems():
self[key] = mapped_function(value)
return self
#------------------------------------------------------------------------------
# [ val_xlist method ] (XList)
# return an XList of the values in the XDict
# Test: test_xdict_val_xlist
#------------------------------------------------------------------------------
def val_xlist(self):
return XList(self.values(), self._getAttributeDict())
#------------------------------------------------------------------------------
# [ max_val method ] (tuple of maximum value and associated key)
# Test: test_xdict_max_val, test_xdict_max_val_strings (strings are alphabetic if not numerals)
#------------------------------------------------------------------------------
def max_val(self):
return max(zip(self.values(), self.keys()))
#------------------------------------------------------------------------------
# [ min_val method ] (tuple of minimum value and associated key)
#------------------------------------------------------------------------------
def min_val(self):
return min(zip(self.values(), self.keys()))
#------------------------------------------------------------------------------
# [ sum_vals method ] (numeric return type dependent upon original value type)
# returns sum of all values in the dictionary
#------------------------------------------------------------------------------
def sum_vals(self):
return sum(self.values())
#------------------------------------------------------------------------------
# [ val_count method ] (integer)
# returns an integer value for the total count of `value_name` in the dictionary values
# Case sensitive test if comparing strings
# Tests: test_xdict_val_count_string, test_xdict_val_count_integer
#------------------------------------------------------------------------------
def val_count(self, value_name):
count = 0
for test_value in self.values():
if value_name == test_value:
count += 1
return count
#------------------------------------------------------------------------------
# [ value_count_ci method ] (integer)
# returns an integer value for the total count of case insensitive `value_name`
# strings/char in the dictionary values. Can include non-string types (ignores them)
# Test: test_xdict_val_count_ci
#------------------------------------------------------------------------------
def val_count_ci(self, value_name):
count = 0
for test_value in self.values():
try:
if value_name.lower() in test_value.lower():
count += 1
except AttributeError: # the test_value was not a string, catch exception and continue count attempt
continue
return count
#------------------------------------------------------------------------------
# XDict Key Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ difference method ] (difference set of keys)
# definition: keys that are included in self, but not in `another_dict`
# Tests: test_xdict_key_difference, test_xdict_key_difference_when_none_present
#------------------------------------------------------------------------------
def difference(self, another_dict):
return set(self.keys()) - set(another_dict.keys())
#------------------------------------------------------------------------------
# [ intersection method ] (intersection set of keys)
# definition: keys that are included in both self and `another_dict`
# Tests: test_xdict_key_intersection, test_xdict_key_intersection_when_none_present
#------------------------------------------------------------------------------
def intersection(self, another_dict):
return set(self.keys()) & set(another_dict.keys())
#------------------------------------------------------------------------------
# [ key_xlist method ] (XList)
# returns an XList of the keys in the XDict
# Test: test_xdict_key_xlist
#------------------------------------------------------------------------------
def key_xlist(self):
return XList(self.keys(), self._getAttributeDict())
#------------------------------------------------------------------------------
# [ random method ] (dictionary)
# return new Python dictionary with single, random key:value pair
# Test: test_xdict_key_random
#------------------------------------------------------------------------------
def random(self):
import random
from Naked.toolshed.python import py_major_version
random_key_list = random.sample(self.keys(), 1)
the_key = random_key_list[0]
return {the_key: self[the_key]}
#------------------------------------------------------------------------------
# [ random_sample method ] (dictionary)
# return new Python dictionary with `number_of_items` random key:value pairs
# Test: test_xdict_key_random_sample
#------------------------------------------------------------------------------
def random_sample(self, number_of_items):
import random
random_key_list = random.sample(self.keys(), number_of_items)
new_dict = {}
for item in random_key_list:
new_dict[item] = self[item]
return new_dict
#------------------------------------------------------------------------------
# [ xitems method ] (tuple)
# Generator method that returns tuples of every key, value in dictionary
# uses appropriate method from Python 2 and 3 interpreters
# Test: test_xdict_xitems
#------------------------------------------------------------------------------
def xitems(self):
from Naked.toolshed.python import py_major_version
if py_major_version() > 2:
return self.items()
else:
return self.iteritems()
#------------------------------------------------------------------------------
# [[ XList class ]]
# An inherited extension to the list object that permits attachment of attributes
#------------------------------------------------------------------------------
class XList(list, NakedObject):
def __init__(self, list_obj, attributes={}, naked_type='XList'):
list.__init__(self, list_obj)
NakedObject.__init__(self, attributes, naked_type)
#------------------------------------------------------------------------------
# XList Operator Overloads
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# + operator overload
# extends XList with one or more other lists (`*other_lists`)
#------------------------------------------------------------------------------
def __add__(self, *other_lists):
try:
for the_list in other_lists:
# add attributes if it is an XList
if hasattr(the_list, '_naked_type_') and (getattr(the_list, '_naked_type_') == 'XList'):
attr_dict = the_list._getAttributeDict() # get XList attribute dictionary
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
# extend the XList items
self.extend(the_list)
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XList with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# += overload
# extends XList with one other list (`another_list`)
#------------------------------------------------------------------------------
def __iadd__(self, another_list):
try:
#add attributes if it is an XList
if hasattr(another_list, '_naked_type_') and (getattr(another_list, '_naked_type_') == 'XList'):
attr_dict = another_list._getAttributeDict() # get XList attribute dictionary
if len(attr_dict) > 0:
for key in attr_dict:
setattr(self, key, attr_dict[key])
# extend the XList items
self.extend(another_list)
return self
except Exception as e:
if DEBUG_FLAG:
sys.stderr.write("Naked Framework Error: unable to combine XList with parameter provided (Naked.toolshed.types.py)")
raise e
#------------------------------------------------------------------------------
# == overload
#------------------------------------------------------------------------------
def __eq__(self, other_obj):
return self.equals(other_obj)
#------------------------------------------------------------------------------
# != overload
#------------------------------------------------------------------------------
def __ne__(self, other_obj):
result = self.equals(other_obj)
if result:
return False # reverse result of the equals method
else:
return True
#------------------------------------------------------------------------------
# [ equals method ] (boolean)
# tests for equality of the XList (type, attributes, list equality)
#------------------------------------------------------------------------------
def equals(self, other_obj):
if self._equal_type(other_obj) and self._equal_attributes(other_obj):
if list(self) == list(other_obj):
return True
else:
return False
else:
return False
#------------------------------------------------------------------------------
# XList Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# XList String Methods
#------------------------------------------------------------------------------
# [ join method ] (string)
# Concatenate strings in the list and return
# Default separator between string list values is an empty string
# Pass separator character(s) as an argument to the method
#------------------------------------------------------------------------------
def join(self, separator=""):
return separator.join(self)
#------------------------------------------------------------------------------
# [ postfix method ] (list of strings)
# Append a string to each list item string
#------------------------------------------------------------------------------
def postfix(self, after):
return [ "".join([x, after]) for x in self ]
#------------------------------------------------------------------------------
# [ prefix method ] (list of strings)
# Prepend a string to each list item string
#------------------------------------------------------------------------------
def prefix(self, before):
return [ "".join([before, x]) for x in self ]
#------------------------------------------------------------------------------
# [ surround method ] (list of strings)
# Surround each list item string with a before and after string argument passed to the method
#------------------------------------------------------------------------------
def surround(self, before, after=""):
if after == "":
after = before
return [ "".join([before, x, after]) for x in self ]
#------------------------------------------------------------------------------
# XList Numeric Methods
#------------------------------------------------------------------------------
# [ max method ] (list dependent type, single value)
# return maximum value from the list items
#------------------------------------------------------------------------------
def max(self):
return max(self)
#------------------------------------------------------------------------------
# [ min method ] (list dependent type, single value)
# return minimum value from the list items
#------------------------------------------------------------------------------
def min(self):
return min(self)
#------------------------------------------------------------------------------
# [ sum method ] (list dependent type, single value)
# return the sum of all list items
#------------------------------------------------------------------------------
def sum(self):
return sum(self)
#------------------------------------------------------------------------------
# XList Data Management Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ count_duplicates method ] (integer)
# returns an integer count of number of duplicate values
#------------------------------------------------------------------------------
def count_duplicates(self):
return len(self) - len(set(self))
#------------------------------------------------------------------------------
# [ remove_duplicates ] (XList)
# returns a new XList with duplicates removed
#------------------------------------------------------------------------------
def remove_duplicates(self):
return XList( set(self), self._getAttributeDict() )
#------------------------------------------------------------------------------
# [ difference method ] (set)
# returns a set containing items in XList that are not contained in `another_list`
#------------------------------------------------------------------------------
def difference(self, another_list):
return set(self) - set(another_list)
#------------------------------------------------------------------------------
# [ intersection method ] (set)
# returns a set containing items that are in both XList and `another_list`
#------------------------------------------------------------------------------
def intersection(self, another_list):
return set(self) & set(another_list)
#------------------------------------------------------------------------------
# XList Function Mapping Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ map_to_items method ] (XList)
# returns original XList with modification of each item based upon `mapped_function`
#------------------------------------------------------------------------------
def map_to_items(self, mapped_function):
# return XList( map(mapped_function, self), self._getAttributeDict() ) - slower
for index, item in enumerate(self):
self[index] = mapped_function(item)
return self
#------------------------------------------------------------------------------
# [ conditional_map_to_items method ] (XList)
# returns original XList with modification of items that meet True condition in
# `conditional_function` with change performed as defined in `mapped_function`
#------------------------------------------------------------------------------
def conditional_map_to_items(self, conditional_function, mapped_function):
for index, item in enumerate(self):
if conditional_function(item):
self[index] = mapped_function(item)
return self
#------------------------------------------------------------------------------
# XList Descriptive Stats Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ count_ci method ] (integer)
# returns an integer count of the number of case-insensitive items that match `test_string`
#------------------------------------------------------------------------------
def count_ci(self, test_string):
count = 0
for item in self:
try:
if test_string.lower() in item.lower():
count += 1
except AttributeError: # the test_value was not a string, catch exception and continue count attempt
continue
return count
#------------------------------------------------------------------------------
# [ random method ] (list)
# returns a single item list with a random element from the original XList
#------------------------------------------------------------------------------
def random(self):
import random
return random.choice(self)
#------------------------------------------------------------------------------
# [ random_sample method ] (list)
# returns a list with one or more random items from the original XList
# number of items determined by the `number_of_items` argument
#------------------------------------------------------------------------------
def random_sample(self, number_of_items):
import random
return random.sample(self, number_of_items)
#------------------------------------------------------------------------------
# [ shuffle method ] (XList)
# randomly shuffle the contents of the list
#------------------------------------------------------------------------------
def shuffle(self):
import random
random.shuffle(self)
return self
#------------------------------------------------------------------------------
# XList Match Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ wildcard_match method ] (list)
# returns a list of items that match the `wildcard` argument
#------------------------------------------------------------------------------
def wildcard_match(self, wildcard):
if hasattr(self, 'nkd_fnmatchcase'):
fnmatchcase = self.nkd_fnmatchcase
else:
from fnmatch import fnmatchcase
self.nkd_fnmatchcase = fnmatchcase
return [ x for x in self if fnmatchcase(x, wildcard) ]
#------------------------------------------------------------------------------
# [ multi_wildcard_match method ] (list)
# returns a list of items that match one or more | separated wildcards passed as string
#------------------------------------------------------------------------------
def multi_wildcard_match(self, wildcards):
if hasattr(self, 'nkd_fnmatchcase'):
fnmatchcase = self.nkd_fnmatchcase
else:
from fnmatch import fnmatchcase
self.nkd_fnmatchcase = fnmatchcase
wc_list = wildcards.split('|')
return_list = []
for wc in wc_list:
temp_list = [ x for x in self if fnmatchcase(x, wc) ]
for result in temp_list:
return_list.append(result)
return return_list
#------------------------------------------------------------------------------
# XList Cast Methods
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# [ xset method ] (XSet)
# return an XSet with unique XList item values and XList attributes
#------------------------------------------------------------------------------
def xset(self):
attr_dict = self._getAttributeDict()
return XSet(set(self), attr_dict)
#------------------------------------------------------------------------------
# [ xfset method ] (XFSet)
# return an XFSet with unique XList item values and XList attributes
#------------------------------------------------------------------------------
def xfset(self):
attr_dict = self._getAttributeDict()
return XFSet(set(self), attr_dict)
#------------------------------------------------------------------------------
# [ xtuple method ] (XTuple)
# returns an XTuple with XList item values and XList attributes
#------------------------------------------------------------------------------
def xtuple(self):
attr_dict = self._getAttributeDict()
return XTuple(tuple(self), attr_dict)
#------------------------------------------------------------------------------
# [[ XMaxHeap class ]]
# max heap queue
#------------------------------------------------------------------------------
from heapq import heappush, heappop
class XMaxHeap(NakedObject):
def __init__(self, attributes={}, naked_type='XMaxHeap'):
NakedObject.__init__(self, attributes, naked_type)
self._queue = []
self._index = 0
# length of the queue
def __len__(self):
return len(self._queue)
# O(log n) complexity
def push(self, the_object, priority):
heappush(self._queue, (-priority, self._index, the_object))
self._index += 1
# O(log n) complexity
def pop(self):
if self._queue:
return heappop(self._queue)[-1]
else:
return None
# push new object and return the highest priority object
def pushpop(self, the_object, priority):
heappush(self._queue, (-priority, self._index, the_object))
self._index += 1
if self._queue:
return heappop(self._queue)[-1]
else:
return None # return None if the queue is empty
# the length of the queue
def length(self):
return len(self._queue)
#------------------------------------------------------------------------------
# [[ XMinHeap class ]]
# min heap queue
#------------------------------------------------------------------------------
from heapq import heappush, heappop
class XMinHeap(NakedObject):
def __init__(self, attributes={}, naked_type='XMinHeap'):
NakedObject.__init__(self, attributes, naked_type)
self._queue = []
self._index = 0
# length of the queue
def __len__(self):
return len(self._queue)
# O(log n) complexity
def push(self, the_object, priority):
heappush(self._queue, (priority, self._index, the_object))
self._index += 1
# O(log n) complexity
def pop(self):
if self._queue:
return heappop(self._queue)[-1]
else:
return None # return None if the queue is empty
# push new object and return the lowest priority object
def pushpop(self, the_object, priority):
heappush(self._queue, (priority, self._index, the_object))
self._index += 1
if self._queue:
return heappop(self._queue)[-1]
else:
return None #return None if the queue is empty
# the length of the queue
def length(self):
return len(self._queue)
#------------------------------------------------------------------------------
# [[ XQueue class ]]
#
#------------------------------------------------------------------------------
from collections import deque
class XQueue(deque, NakedObject):
def __init__(self, initial_iterable=[], attributes={}, max_length=10, naked_type='XQueue'):
deque.__init__(self, initial_iterable, max_length)
NakedObject.__init__(self, attributes, naked_type)
#------------------------------------------------------------------------------
# [[ XSet class ]]
# An inherited extension to the mutable set object that permits attribute assignment
# Inherits from set and from NakedObject (see methods in NakedObject at top of this module
#------------------------------------------------------------------------------
class XSet(set, NakedObject):
def __init__(self, set_obj, attributes={}, naked_type='XSet'):
set.__init__(self, set_obj)
NakedObject.__init__(self, attributes, naked_type)
# += operator overload to extend the XSet with a second set
def __iadd__(self, another_set):
self.update(another_set)
return self
def xlist(self):
attr_dict = self._getAttributeDict()
return XList(list(self), attr_dict)
def xfset(self):
attr_dict = self._getAttributeDict()
return XFSet(self, attr_dict)
#------------------------------------------------------------------------------
# [[ XFSet class ]]
# An inherited extension to the immutable frozenset object that permits attribute assignment
# Immutable so there is no setter method, attributes must be set in the constructor
#------------------------------------------------------------------------------
class XFSet(frozenset):
def __new__(cls, the_set, attributes={}, naked_type="XFSet"):
set_obj = frozenset.__new__(cls, the_set)
if len(attributes) > 0:
for key in attributes:
setattr(set_obj, key, attributes[key])
setattr(set_obj, '_naked_type_', naked_type) # set the naked extension type as an attribute (NakedObject does this for mutable classes)
return set_obj
def _getAttributeDict(self):
return self.__dict__
def xlist(self):
attr_dict = self._getAttributeDict()
return XList(list(self), attr_dict, naked_type="XList")
def xset(self):
attr_dict = self._getAttributeDict()
return XSet(self, attr_dict, naked_type="XSet")
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
#------------------------------------------------------------------------------
# [[ XString class ]]
# An inherited extension to the immutable string object that permits attribute assignment
# Immutable so there is no setter method, attributes must be set in the constructor
# Python 2: byte string by default, can cast to normalized UTF-8 with XString().unicode() method
# Python 3: string (that permits unicode) by default, can normalize with XString().unicode() method
#------------------------------------------------------------------------------
class XString(str):
def __new__(cls, string_text, attributes={}, naked_type='XString'):
str_obj = str.__new__(cls, string_text)
if len(attributes) > 0:
for key in attributes:
setattr(str_obj, key, attributes[key])
setattr(str_obj, '_naked_type_', naked_type)
return str_obj
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the XString instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
## TODO: see where + vs. join breakpoint becomes important
def concat(self, *strings):
str_list = []
for x in strings:
str_list.append(x)
return "".join(str_list)
# fastest substring search truth test
def contains(self, substring):
return substring in self
# split the string on one or more delimiters, return list
# if up to two chars, then uses str.split(), if more chars then use re.split
def xsplit(self, split_delimiter):
length = len(split_delimiter)
if length > 2:
import re
split_delimiter = "".join([ '[', split_delimiter, ']' ])
return re.split(split_delimiter, self)
elif length > 1:
delim2 = split_delimiter[1]
first_list = self.split(split_delimiter[0])
result_list = []
for item in first_list:
for subitem in item.split(delim2):
result_list.append(subitem)
return result_list
else:
return self.split(split_delimiter)
# split the string on one or more characters and return items in set
def xsplit_set(self, split_delimiter):
return set(self.xsplit(split_delimiter))
# str begins with substring - faster than str.startswith()
def begins(self, begin_string):
return begin_string in self[0:len(begin_string)]
# str ends with substring - faster than str.endswith()
def ends(self, end_string):
return end_string in self[-len(end_string):]
# case sensitive wildcard match on the XString (boolean returned)
def wildcard_match(self, wildcard):
from fnmatch import fnmatchcase
return fnmatchcase(self, wildcard)
# convert string to normalized UTF-8 in Python 2 and 3 (##TODO: convert to XUnicode with attributes?)
def unicode(self):
from sys import version_info
from unicodedata import normalize
if version_info[0] == 2:
return normalize('NFKD', self.decode('UTF-8'))
else:
return normalize('NFKD', self)
# this version works
class XUnicode:
def __init__(self, string_text, attributes={}, naked_type='XUnicode'):
import sys
import unicodedata
norm_text = unicodedata.normalize('NFKD', string_text)
class XUnicode_2(unicode):
def __new__(cls, the_string_text, attributes={}, naked_type='XUnicode2'):
str_obj = unicode.__new__(cls, the_string_text)
if len(attributes) > 0:
for key in attributes:
setattr(str_obj, key, attributes[key])
setattr(str_obj, '_naked_type_', naked_type) # set the type to XUnicode2 for Py 2 strings
return str_obj
class XUnicode_3(str):
def __new__(cls, the_string_text, attributes={}, naked_type='XUnicode3'):
str_obj = str.__new__(cls, the_string_text)
if len(attributes) > 0:
for key in attributes:
setattr(str_obj, key, attributes[key])
setattr(str_obj, '_naked_type_', naked_type) # set the type to XUnicode3 for Py 3 strings
return str_obj
if sys.version_info[0] == 2:
self.obj = XUnicode_2(norm_text, attributes)
self.norm_unicode = norm_text
self.naked_u_string = self.obj.encode('utf-8') # utf-8 encoded byte string
elif sys.version_info[0] == 3:
self.naked_u_string = XUnicode_3(norm_text, attributes).encode('utf-8') # ?
def __str__(self):
# return self.naked_u_string
return self.obj
def __repr__(self):
return self.naked_u_string
def __getattr__(self, the_attribute):
return self.obj.__dict__[the_attribute]
def __cmp__(self, other_string):
return hash(self.naked_u_string) == hash(other_string)
# TODO: add check for same attributes
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the NakedObject instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
#------------------------------------------------------------------------------
# [[ XTuple class ]]
#
#------------------------------------------------------------------------------
class XTuple(tuple):
def __new__(cls, the_tuple, attributes={}, naked_type='XTuple'):
tup_obj = tuple.__new__(cls, the_tuple)
if len(attributes) > 0:
for key in attributes:
setattr(tup_obj, key, attributes[key])
setattr(tup_obj, '_naked_type_', naked_type)
return tup_obj
#------------------------------------------------------------------------------
# [ _getAttributeDict method ] (dictionary)
# returns a dictionary of the NakedObject instance attributes
#------------------------------------------------------------------------------
def _getAttributeDict(self):
return self.__dict__
#------------------------------------------------------------------------------
# [ type method ] (string)
# returns the Naked type extension string that is set in the constructor for each object type
#------------------------------------------------------------------------------
def type(self):
if hasattr(self, '_naked_type_'):
return self._naked_type_
else:
return None
if __name__ == '__main__':
pass
# no = nobj({"version":"1.0.1", "test":"code"})
# print(no)
# print(no.version)
# print(no.test)
# nl = XList([1, 2, 3, 1, 2, 5], {"version":"1.0.1", "test":"code"})
# print(nl.count_duplicates())
# the_list = list(range(5000))
# nl = XList(the_list)
# nq = XPriorityQueue()
# nq.push('test', 5)
# nq.push('one', 3)
# nq.push('another', 4)
# print(nq.pop())
# print(nq.pop())
# print(nq.pop())
# nl = XList([2, 2, 2, 'another'], {'p': 'attribute'})
# print(nl)
# print(nl.count_item(2))
# nq = XQueue(nl, max_length=2)
# print(nq)
# xs = XSet({'test', 'true', 'false'}, {'bonus': 'candy', 'test': 'another'})
# xs += {'bogus', 'yep'}
# print(xs)
# xd = XDict({'test2': 0, 'is': 1}, {'a': '1', 'b': '2'})
# ad = {'test': 0, 'is': 2}
# ld = xd.intersection(ad)
# print(ld)
# xd = xd + ad + ld
# print(xd.map_to_vals(pr))
# print(xd.a)
# print(xd)
# print(xd.a)
# print(xd.min_val())
# print(xd.conditional_map_to_vals(matcher, resulter))
# nl = XList([ 'test.txt', 'bogus.txt', 'test.py', 'another.rb', 'est.doc', 'est.py' ])
# print(nl.multi_wildcard_match('*.py|*.txt|*.doc'))
# xstr = XString("Hey! Cœur It's Bengali ব য,\nand here is some more ২")
# ustr = xstr.unicode()
# print(isinstance(ustr, bytes))
# print(xstr)

@ -0,0 +1,20 @@
Copyright (c) 2017-2019 Ingy döt Net
Copyright (c) 2006-2016 Kirill Simonov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,40 @@
Metadata-Version: 2.1
Name: PyYAML
Version: 5.3
Summary: YAML parser and emitter for Python
Home-page: https://github.com/yaml/pyyaml
Author: Kirill Simonov
Author-email: xi@resolvent.net
License: MIT
Download-URL: https://pypi.org/project/PyYAML/
Platform: Any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Cython
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup
YAML is a data serialization format designed for human readability
and interaction with scripting languages. PyYAML is a YAML parser
and emitter for Python.
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
support, capable extension API, and sensible error messages. PyYAML
supports standard YAML tags and provides Python-specific tags that
allow to represent an arbitrary Python object.
PyYAML is applicable for a broad range of tasks from complex
configuration files to object serialization and persistence.

@ -0,0 +1,40 @@
PyYAML-5.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
PyYAML-5.3.dist-info/LICENSE,sha256=oq25yVm3l0lKDvgL32DiLbJ0nuPgwJCFVuPrVI-WfFY,1101
PyYAML-5.3.dist-info/METADATA,sha256=qeUmOwAa8JaIGvO7rR36WWVTAyA6OjLbv80lirmn4KI,1688
PyYAML-5.3.dist-info/RECORD,,
PyYAML-5.3.dist-info/WHEEL,sha256=xhTAlQlEzHPebOMFd-mhU4DM_uRYSil3AJ61fHfeWHQ,102
_yaml.cp37-win32.pyd,sha256=F0-gY63-wzdqJ9iYq4g-79svSHDp8bszK0-2jO4Gz3M,231424
yaml/__init__.py,sha256=d28oT0Lc_XTrMwdoyG_fnl7KLfZzPHAbewmELDwVkyY,13168
yaml/__pycache__/__init__.cpython-37.pyc,sha256=rCcebvcUhx0FVRO1KRSCSo-ALdzIYtjyTD62Tk52eJE,11721
yaml/__pycache__/composer.cpython-37.pyc,sha256=cOpEfSk4Fq-jFkPsieHN2kJcmcr2Vc6D8NVvYTPOE1o,3484
yaml/__pycache__/constructor.cpython-37.pyc,sha256=06qatUtXJKnpfjaT2pfJc-3XmcAlH_-6afhzOQo6Wsw,20074
yaml/__pycache__/cyaml.cpython-37.pyc,sha256=gyoH1zVnyV6BTcnDi4eM1HPYVt5XE-D4S4HZELEo4x4,3649
yaml/__pycache__/dumper.cpython-37.pyc,sha256=s3rc-ZaF4jFpa-1Oq4ZZVMKaxaWmyDbgvnUYVMjvdyI,2024
yaml/__pycache__/emitter.cpython-37.pyc,sha256=yn8qKLXPiFVHPkalKUOxvqt6c1GDpvDv64flUyA-fQw,25274
yaml/__pycache__/error.cpython-37.pyc,sha256=3nFo2OVqw39xQ2n8Xlb8YVDFtIk6QYnrQseaqzWqxgQ,2235
yaml/__pycache__/events.cpython-37.pyc,sha256=fd9PwYCVVRyLfNWoWJlFJTKKxwxqHJ9ptZz28J4pHwo,4001
yaml/__pycache__/loader.cpython-37.pyc,sha256=zMnbLaDnYxc_9DW3ath8WgEme7Cp8hYMWSVbgoYOD-0,2233
yaml/__pycache__/nodes.cpython-37.pyc,sha256=O1LH_BDmPYD52se6KfoBWlee7CPGtKI-kMv75EgnC00,1679
yaml/__pycache__/parser.cpython-37.pyc,sha256=mysaVAzDSPgpwNozJAHCBAIF2_ZwEkFAx5FDru0Ajvs,11829
yaml/__pycache__/reader.cpython-37.pyc,sha256=KNWgMf-RIz7QPmDwNDd-5d_ZO5ZIQbH66os3I0WMAlk,4442
yaml/__pycache__/representer.cpython-37.pyc,sha256=TuoUxqnBNU6w_RcE4nGkudplMHg0XvPc_PzOiXu5fEI,10065
yaml/__pycache__/resolver.cpython-37.pyc,sha256=eUi337rMdeLYgfEULvNcDQw9OvF-rXXnPKDA-p5Sroc,5415
yaml/__pycache__/scanner.cpython-37.pyc,sha256=zkmXD0FYIfQcr6rRNPsVvrKbNhpYNdgrXkDH-k1lNMw,25775
yaml/__pycache__/serializer.cpython-37.pyc,sha256=7V9jHBaequ3D4yC7q8Zg1EOOwnmBIlZGKzdbkJO04aY,3314
yaml/__pycache__/tokens.cpython-37.pyc,sha256=PEcIbV522wfYzKavUEos4QkZfFWxAhLmpF_9mmkZgjU,5178
yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883
yaml/constructor.py,sha256=4Pd2pssgKUMGLdS_kW6A4SwC7q0T13-sBrATvNQZCZ0,27321
yaml/cyaml.py,sha256=LiMkvchNonfoy1F6ec9L2BiUz3r0bwF4hympASJX1Ic,3846
yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837
yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006
yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533
yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445
yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061
yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440
yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495
yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794
yaml/representer.py,sha256=82UM3ZxUQKqsKAF4ltWOxCS6jGPIFtXpGs7mvqyv4Xs,14184
yaml/resolver.py,sha256=DJCjpQr8YQCEYYjKEYqTl0GrsZil2H4aFOI9b0Oe-U4,8970
yaml/scanner.py,sha256=KeQIKGNlSyPE8QDwionHxy9CgbqE5teJEz05FR9-nAg,51277
yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165
yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.33.6)
Root-Is-Purelib: false
Tag: cp37-cp37m-win32

@ -0,0 +1,91 @@
Documentation: http://chrissimpkins.github.io/crypto/
Description
-------------
crypto provides a simple interface to symmetric Gnu Privacy Guard (gpg) encryption and decryption for one or more files on Unix and Linux platforms. It runs on top of gpg and requires a gpg install on your system. Encryption is performed with the AES256 cipher algorithm. `Benchmarks relative to default gpg settings are available for text and binary file mime types <https://chrissimpkins.github.io/crypto/benchmarks.html>`_.
crypto provides a number of options including automated tar archives of multiple files prior to encryption, portable ASCII armored encryption formatting, and SHA256 hash digest generation for your encrypted files. You can view all available options in the `usage documentation <http://chrissimpkins.github.io/crypto/usage.html>`_ or with the ``--help`` option.
Tested in cPython 2.7.x, 3.4.x, and pypy 2.4.x (Python version 2.7.9)
Install
---------
Install with ``pip`` using the command:
.. code-block:: bash
$ pip install crypto
or `download the source repository <https://github.com/chrissimpkins/crypto/tarball/master>`_, unpack it, and navigate to the top level of the repository. Then enter:
.. code-block:: bash
$ python setup.py install
Upgrade
-----------
You can upgrade your crypto version with the command:
.. code-block:: bash
$ pip install --upgrade crypto
Usage
---------
Encryption (crypto)
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
$ crypto <options> [file path] <file path 2...>
.. code-block:: bash
$ crypto <options> [directory path] <directory path 2...>
Decryption (decrypto)
^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
$ decrypto <options> [file path] <file path 2...>
.. code-block:: bash
$ decrypto <options> [directory path] <directory path 2...>
You can find all available options in the `documentation <http://chrissimpkins.github.io/crypto/usage.html>`_ or by using one of the following commands:
.. code-block:: bash
$ crypto --help
$ decrypto --help
Frequently Asked Questions
-------------------------------
`FAQ link <http://chrissimpkins.github.io/crypto/faq.html>`_
Issue Reporting
-------------------
Issue reporting is available on the `GitHub repository <https://github.com/chrissimpkins/crypto/issues>`_
Changelog
------------
`Changelog link <http://chrissimpkins.github.io/crypto/changelog.html>`_

@ -0,0 +1,116 @@
Metadata-Version: 2.0
Name: crypto
Version: 1.4.1
Summary: Simple symmetric GPG file encryption and decryption
Home-page: https://github.com/chrissimpkins/crypto
Author: Christopher Simpkins
Author-email: git.simpkins@gmail.com
License: MIT license
Keywords: encryption,decryption,gpg,pgp,openpgp,cipher,AES256,crypto,cryptography,security,privacy
Platform: any
Classifier: Intended Audience :: End Users/Desktop
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Security
Classifier: Development Status :: 5 - Production/Stable
Classifier: Natural Language :: English
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Operating System :: Unix
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Requires-Dist: Naked
Requires-Dist: shellescape
Documentation: http://chrissimpkins.github.io/crypto/
Description
-------------
crypto provides a simple interface to symmetric Gnu Privacy Guard (gpg) encryption and decryption for one or more files on Unix and Linux platforms. It runs on top of gpg and requires a gpg install on your system. Encryption is performed with the AES256 cipher algorithm. `Benchmarks relative to default gpg settings are available for text and binary file mime types <https://chrissimpkins.github.io/crypto/benchmarks.html>`_.
crypto provides a number of options including automated tar archives of multiple files prior to encryption, portable ASCII armored encryption formatting, and SHA256 hash digest generation for your encrypted files. You can view all available options in the `usage documentation <http://chrissimpkins.github.io/crypto/usage.html>`_ or with the ``--help`` option.
Tested in cPython 2.7.x, 3.4.x, and pypy 2.4.x (Python version 2.7.9)
Install
---------
Install with ``pip`` using the command:
.. code-block:: bash
$ pip install crypto
or `download the source repository <https://github.com/chrissimpkins/crypto/tarball/master>`_, unpack it, and navigate to the top level of the repository. Then enter:
.. code-block:: bash
$ python setup.py install
Upgrade
-----------
You can upgrade your crypto version with the command:
.. code-block:: bash
$ pip install --upgrade crypto
Usage
---------
Encryption (crypto)
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
$ crypto <options> [file path] <file path 2...>
.. code-block:: bash
$ crypto <options> [directory path] <directory path 2...>
Decryption (decrypto)
^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
$ decrypto <options> [file path] <file path 2...>
.. code-block:: bash
$ decrypto <options> [directory path] <directory path 2...>
You can find all available options in the `documentation <http://chrissimpkins.github.io/crypto/usage.html>`_ or by using one of the following commands:
.. code-block:: bash
$ crypto --help
$ decrypto --help
Frequently Asked Questions
-------------------------------
`FAQ link <http://chrissimpkins.github.io/crypto/faq.html>`_
Issue Reporting
-------------------
Issue reporting is available on the `GitHub repository <https://github.com/chrissimpkins/crypto/issues>`_
Changelog
------------
`Changelog link <http://chrissimpkins.github.io/crypto/changelog.html>`_

@ -0,0 +1,28 @@
../../Scripts/crypto.exe,sha256=p3AgdHe-v7ncFcENaBUjHJ10ndwkAZd6dnzRmZKYpus,93000
../../Scripts/decrypto.exe,sha256=MYU2xn0LykZbbYskB8hTEIMqIKPNE9TTNDS3wkW1SbI,93008
crypto-1.4.1.data/scripts/crypto,sha256=JiOIH9vUcNmsPUqHi3sD7wa-KshHSSHsWwYxdJxquFU,287
crypto-1.4.1.data/scripts/decrypto,sha256=GFVx1pyc7wga_NuKaO5IN4VpiC-iB1nXFIzvwRKs-QI,291
crypto-1.4.1.dist-info/DESCRIPTION.rst,sha256=cUnYN7Bc2SHYRPCbrgoiwqxsilKu-F870exbHPzYyqg,2406
crypto-1.4.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
crypto-1.4.1.dist-info/METADATA,sha256=kQ8T3QfQ00YZ0ETfqAgpzT7JjQZyAtcbpdD4eO-LyfY,3354
crypto-1.4.1.dist-info/RECORD,,
crypto-1.4.1.dist-info/WHEEL,sha256=SXYYsi-y-rEGIva8sB8iKF6bAFD6YDhmqHX5hI3fc0o,110
crypto-1.4.1.dist-info/entry_points.txt,sha256=c4pXwtenCFUlTF9DHcgCWqXZChpJwNtbSjtfQMhrm3M,79
crypto-1.4.1.dist-info/pydist.json,sha256=Q2O_1hp0_7IBZ-JTH9MYE5-GNhTxeT1KqjRvp6U8YAs,1261
crypto-1.4.1.dist-info/top_level.txt,sha256=iQrOUgmGXiXK01vJOH4JP-6x-yip7JIM4OEshevZ9wE,7
crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
crypto/__pycache__/__init__.cpython-37.pyc,,
crypto/__pycache__/app.cpython-37.pyc,,
crypto/__pycache__/decryptoapp.cpython-37.pyc,,
crypto/__pycache__/settings.cpython-37.pyc,,
crypto/app.py,sha256=m9usVyS7G-vg7YYx7rVV1DWohss5xlKKq5vV-viSi8o,13952
crypto/decryptoapp.py,sha256=5hJEh55vyHSgMUkIp2PdYn5P1Z6qkFdrAnsu8EhJZ8c,22448
crypto/library/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
crypto/library/__pycache__/__init__.cpython-37.pyc,,
crypto/library/__pycache__/cryptor.cpython-37.pyc,,
crypto/library/__pycache__/hash.cpython-37.pyc,,
crypto/library/__pycache__/package.cpython-37.pyc,,
crypto/library/cryptor.py,sha256=0A6KMRsRo7UpfFw0qTbaVByqIRqO4bGSbckgR9fH-RQ,8934
crypto/library/hash.py,sha256=HVO5NcCRVHJRYOIAMTHlxzk1wWAeYuon2QwiRHJJaAY,847
crypto/library/package.py,sha256=mTXHpmJFRKqx_KGRN1bUfSei8duBARZKtH4hBQzXAi4,1754
crypto/settings.py,sha256=d--yWR6fCw10JO3tyQhCY1z36PzPsW7ElRmcikNd8vg,4506

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.22.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

@ -0,0 +1,4 @@
[console_scripts]
crypto = crypto.app:main
decrypto = crypto.decryptoapp:main

@ -0,0 +1 @@
{"license": "MIT license", "exports": {"console_scripts": {"crypto": "crypto.app:main", "decrypto": "crypto.decryptoapp:main"}}, "document_names": {"description": "DESCRIPTION.rst"}, "name": "crypto", "metadata_version": "2.0", "contacts": [{"role": "author", "email": "git.simpkins@gmail.com", "name": "Christopher Simpkins"}], "generator": "bdist_wheel (0.22.0)", "commands": {"wrap_console": {"crypto": "crypto.app:main", "decrypto": "crypto.decryptoapp:main"}}, "summary": "Simple symmetric GPG file encryption and decryption", "project_urls": {"Home": "https://github.com/chrissimpkins/crypto"}, "platform": "any", "run_requires": [{"requires": ["Naked", "shellescape"]}], "version": "1.4.1", "keywords": "encryption,decryption,gpg,pgp,openpgp,cipher,AES256,crypto,cryptography,security,privacy", "classifiers": ["Intended Audience :: End Users/Desktop", "Topic :: Security :: Cryptography", "Topic :: Security", "Development Status :: 5 - Production/Stable", "Natural Language :: English", "License :: OSI Approved :: MIT License", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3"], "extras": []}

@ -0,0 +1,262 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
# crypto
# Copyright 2015 Christopher Simpkins
# MIT license
# ------------------------------------------------------------------------------
# Application start
def main():
import sys
import getpass
from Naked.commandline import Command
from Naked.toolshed.system import dir_exists, file_exists, list_all_files, make_path, stderr
# ------------------------------------------------------------------------------------------
# [ Instantiate command line object ]
# used for all subsequent conditional logic in the CLI application
# ------------------------------------------------------------------------------------------
c = Command(sys.argv[0], sys.argv[1:])
# ------------------------------------------------------------------------------------------
# [ VALIDATION LOGIC ] - early validation of appropriate command syntax
# Test that user entered at least one argument to the executable, print usage if not
# ------------------------------------------------------------------------------------------
if not c.command_suite_validates():
from crypto.settings import usage as crypto_usage
print(crypto_usage)
sys.exit(1)
# ------------------------------------------------------------------------------------------
# [ HELP, VERSION, USAGE LOGIC ]
# Naked framework provides default help, usage, and version commands for all applications
# --> settings for user messages are assigned in the lib/crypto/settings.py file
# ------------------------------------------------------------------------------------------
if c.help(): # User requested crypto help information
from crypto.settings import help as crypto_help
print(crypto_help)
sys.exit(0)
elif c.usage(): # User requested crypto usage information
from crypto.settings import usage as crypto_usage
print(crypto_usage)
sys.exit(0)
elif c.version(): # User requested crypto version information
from crypto.settings import app_name, major_version, minor_version, patch_version
version_display_string = app_name + ' ' + major_version + '.' + minor_version + '.' + patch_version
print(version_display_string)
sys.exit(0)
# ------------------------------------------------------------------------------------------
# [ APPLICATION LOGIC ]
#
# ------------------------------------------------------------------------------------------
elif c.argc > 1:
# code for multi-file processing and commands that include options
# ASCII ARMOR SWITCH
ascii_armored = False
if c.option('--armor') or c.option('-a'):
ascii_armored = True
# MAX COMPRESS / COMPRESS ALL SWITCH
max_compress = False
if c.option('--space'):
max_compress = True
# NO COMPRESSION SWITCH
no_compress = False
if c.option('--speed'):
no_compress = True
# SECURE HASH DIGEST REPORT SWITCH
report_checksum = False
if c.option('--hash'):
report_checksum = True
# TAR FOLDERS SWITCH
tar_folders = False
if c.option('--tar'):
tar_folders = True
directory_list = [] # directory paths included in the user entered paths from the command line
tar_directory_list = [] # directories, which need to be packaged as tar archives
file_list = [] # file paths included in the user entered paths from the command line (and inside directories entered)
# dot and .crypt file flags for exclusion testing
contained_dot_file = False
contained_crypt_file = False
# determine if argument is an existing file or directory
for argument in c.argv:
if file_exists(argument):
if argument.endswith('.crypt'): # do not include previously encrypted files
contained_crypt_file = True
else:
file_list.append(argument) # add appropriate file paths to the file_list
elif dir_exists(argument):
directory_list.append(argument) # if it is a directory, add path to the directory_list
# add all file paths from user specified directories to the file_list
if len(directory_list) > 0:
if not tar_folders:
for directory in directory_list:
directory_file_list = list_all_files(directory)
for contained_file in directory_file_list:
if contained_file[0] == ".":
contained_dot_file = True # change the flag + is not included in file_list intentionally (no dot files)
elif contained_file.endswith('.crypt'):
contained_crypt_file = True # change the flag + is not included in file_list intentionally (no previously encrypted files)
else:
# otherwise add to the list for encryption
contained_file_path = make_path(directory, contained_file)
file_list.append(contained_file_path)
else:
# create (uncompressed) tar archive for every targeted folder and add the resulting archive to the file_list
# do not start tar file creation, yet (!) - it is more convenient for the user to first enter the passphrase then start processing
for directory in directory_list:
directory_file_path = directory + '.tar'
tar_directory_list.append(directory)
file_list.append(directory_file_path)
# confirm that there are files to be encrypted, if not warn user
if len(file_list) == 0:
if contained_dot_file is True or contained_crypt_file is True:
stderr("There were no files identified for encryption. crypto does not encrypt dot files or previously encrypted '.crypt' files.")
sys.exit(1)
else:
stderr("Unable to identify files for encryption")
sys.exit(1)
else:
# file_list should contain all filepaths from either user specified file paths or contained in top level of directory, encrypt them
passphrase = getpass.getpass("Please enter your passphrase: ")
if len(passphrase) == 0: # confirm that user entered a passphrase
stderr("You did not enter a passphrase. Please repeat your command and try again.")
sys.exit(1)
passphrase_confirm = getpass.getpass("Please enter your passphrase again: ")
if passphrase == passphrase_confirm:
# create temporary tar-files
tar_list = []
if len(tar_directory_list) > 0:
from crypto.library import package
tar_list = package.generate_tar_files(tar_directory_list)
for t in tar_list:
if t not in file_list: # check to confirm that the tar archive is in the list of files to encrypt
if file_exists(t):
# append the tarfile to the file_list for encryption if it was not included in the file list for encryption
file_list.append(t)
else:
stderr("There was an error with the tar archive creation. Please try again.", exit=1)
from crypto.library.cryptor import Cryptor
the_cryptor = Cryptor(passphrase)
# run encryption based upon any passed switches
if ascii_armored:
if max_compress:
the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=True, armored=True, checksum=report_checksum)
elif no_compress:
the_cryptor.encrypt_files(file_list, force_nocompress=True, force_compress=False, armored=True, checksum=report_checksum)
else:
the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=False, armored=True, checksum=report_checksum)
else:
if max_compress:
the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=True, armored=False, checksum=report_checksum)
elif no_compress:
the_cryptor.encrypt_files(file_list, force_nocompress=True, force_compress=False, armored=False, checksum=report_checksum)
else:
the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=False, armored=False, checksum=report_checksum)
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
the_cryptor.cleanup()
# tmp tar file removal (generated with package.generate_tar_files function above)
if len(tar_list) > 0:
from crypto.library import package
package.remove_tar_files(tar_list)
else:
# passphrases did not match, report to user and abort
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
stderr("The passphrases did not match. Please enter your command again.")
sys.exit(1)
elif c.argc == 1:
# simple single file or directory processing with default settings
path = c.arg0
if file_exists(path):
# it is a file, encrypt the single file with default settings
# confirm that it is not already encrypted, abort if so
if path.endswith('.crypt'):
stderr("You are attempting to encrypt an encrypted file. Please delete the .crypt file and repeat encryption with the original file if this is your intent.")
sys.exit(1)
# if passes test above, obtain passphrase from the user
passphrase = getpass.getpass("Please enter your passphrase: ")
if len(passphrase) == 0: # confirm that user entered a passphrase
stderr("You did not enter a passphrase. Please repeat your command and try again.")
sys.exit(1)
passphrase_confirm = getpass.getpass("Please enter your passphrase again: ")
if passphrase == passphrase_confirm:
from crypto.library.cryptor import Cryptor
the_cryptor = Cryptor(passphrase)
the_cryptor.encrypt_file(path)
the_cryptor.cleanup()
else:
stderr("The passphrases did not match. Please enter your command again.")
sys.exit(1)
elif dir_exists(path):
# it is a directory, encrypt all top level files with default settings
dirty_directory_file_list = list_all_files(path)
# remove dot files and previously encrypted files (with .crypt suffix) from the list of directory files
clean_directory_file_list = [x for x in dirty_directory_file_list if x[0] != "." and x.endswith(".crypt") is False] # remove dotfiles and .crypt files
# confirm that there are still files in the list after the dot files and encrypted files are removed
if len(clean_directory_file_list) == 0:
stderr("There are no unencrypted files in the directory.")
sys.exit(1)
# create relative file paths for each file in the clean_directory_file_list
clean_directory_file_list_relpaths = []
for clean_file in clean_directory_file_list:
new_file_path = make_path(path, clean_file)
clean_directory_file_list_relpaths.append(new_file_path)
# prompt for the passphrase
passphrase = getpass.getpass("Please enter your passphrase: ")
if len(passphrase) == 0: # confirm that user entered a passphrase
stderr("You did not enter a passphrase. Please repeat your command and try again.")
sys.exit(1)
passphrase_confirm = getpass.getpass("Please enter your passphrase again: ")
if passphrase == passphrase_confirm:
from crypto.library.cryptor import Cryptor
the_cryptor = Cryptor(passphrase)
the_cryptor.encrypt_files(clean_directory_file_list_relpaths) # encrypt the list of directory files
the_cryptor.cleanup()
else:
# passphrases do not match
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
stderr("The passphrases did not match. Please enter your command again.")
sys.exit(1)
else:
# error message, not a file or directory. user entry error
stderr("The path that you entered does not appear to be an existing file or directory. Please try again.")
sys.exit(1)
# ------------------------------------------------------------------------------------------
# [ DEFAULT MESSAGE FOR MATCH FAILURE ]
# Message to provide to the user when all above conditional logic fails to meet a true condition
# ------------------------------------------------------------------------------------------
else:
print("Could not complete your request. Please try again.")
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,380 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
# decrypto
# Copyright 2015 Christopher Simpkins
# MIT license
# ------------------------------------------------------------------------------
# Application start
def main():
import os
import sys
from time import sleep
import getpass
import tarfile
from Naked.commandline import Command
from Naked.toolshed.shell import execute, muterun
from Naked.toolshed.system import dir_exists, file_exists, list_all_files, make_path, stdout, stderr, is_dir
from shellescape import quote
# ------------------------------------------------------------------------------------------
# [ Instantiate command line object ]
# used for all subsequent conditional logic in the CLI application
# ------------------------------------------------------------------------------------------
c = Command(sys.argv[0], sys.argv[1:])
# ------------------------------------------------------------------------------------------
# [ VALIDATION LOGIC ] - early validation of appropriate command syntax
# Test that user entered at least one argument to the executable, print usage if not
# ------------------------------------------------------------------------------------------
if not c.command_suite_validates():
from crypto.settings import usage as crypto_usage
print(crypto_usage)
sys.exit(1)
# ------------------------------------------------------------------------------------------
# [ HELP, VERSION, USAGE LOGIC ]
# Naked framework provides default help, usage, and version commands for all applications
# --> settings for user messages are assigned in the lib/crypto/settings.py file
# ------------------------------------------------------------------------------------------
if c.help(): # User requested crypto help information
from crypto.settings import help as crypto_help
print(crypto_help)
sys.exit(0)
elif c.usage(): # User requested crypto usage information
from crypto.settings import usage as crypto_usage
print(crypto_usage)
sys.exit(0)
elif c.version(): # User requested crypto version information
from crypto.settings import app_name, major_version, minor_version, patch_version
version_display_string = app_name + ' ' + major_version + '.' + minor_version + '.' + patch_version
print(version_display_string)
sys.exit(0)
# ------------------------------------------------------------------------------------------
# [ APPLICATION LOGIC ]
#
# ------------------------------------------------------------------------------------------
elif c.argc > 1:
# code for multi-file processing and commands that include options
use_standard_output = False # print to stdout flag
use_file_overwrite = False # overwrite existing file
untar_archives = True # untar decrypted tar archives, true by default
# set user option flags
if c.option('--stdout') or c.option('-s'):
use_standard_output = True
if c.option('--overwrite') or c.option('-o'):
use_file_overwrite = True
if c.option('--nountar'):
untar_archives = False
directory_list = [] # directory paths included in the user entered paths from the command line
file_list = [] # file paths included in the user entered paths from the command line (and inside directories entered)
for argument in c.argv:
if file_exists(argument): # user included a file, add it to the file_list for decryption
if argument.endswith('.crypt'):
file_list.append(argument) # add .crypt files to the list of files for decryption
elif argument.endswith('.gpg'):
file_list.append(argument)
elif argument.endswith('.asc'):
file_list.append(argument)
elif argument.endswith('.pgp'):
file_list.append(argument)
else:
# cannot identify as an encrypted file, give it a shot anyways but warn user
file_list.append(argument)
stdout("Could not confirm that '" + argument + "' is encrypted based upon the file type. Attempting decryption. Keep your fingers crossed...")
elif dir_exists(argument): # user included a directory, add it to the directory_list
directory_list.append(argument)
else:
if argument[0] == "-":
pass # if it is an option, do nothing
else:
stderr("'" + argument + "' does not appear to be an existing file or directory. Aborting decryption attempt for this request.")
# unroll the contained directory files into the file_list IF they are encrypted file types
if len(directory_list) > 0:
for directory in directory_list:
directory_file_list = list_all_files(directory)
for contained_file in directory_file_list:
if contained_file.endswith('.crypt'):
file_list.append(make_path(directory, contained_file)) # include the file with a filepath 'directory path/contained_file path'
elif contained_file.endswith('.gpg'):
file_list.append(make_path(directory, contained_file))
elif contained_file.endswith('asc'):
file_list.append(make_path(directory, contained_file))
elif contained_file.endswith('.pgp'):
file_list.append(make_path(directory, contained_file))
# confirm that there are files for decryption, if not abort
if len(file_list) == 0:
stderr("Could not identify files for decryption")
sys.exit(1)
# get passphrase used to symmetrically decrypt the file
passphrase = getpass.getpass("Please enter your passphrase: ")
if len(passphrase) == 0: # confirm that user entered a passphrase
stderr("You did not enter a passphrase. Please repeat your command and try again.")
sys.exit(1)
passphrase_confirm = getpass.getpass("Please enter your passphrase again: ")
if passphrase == passphrase_confirm:
# begin decryption of each requested file. the directory path was already added to the file path above
for encrypted_file in file_list:
# create the decrypted file name
decrypted_filename = ""
if encrypted_file.endswith('.crypt'):
decrypted_filename = encrypted_file[0:-6]
elif encrypted_file.endswith('.gpg') or encrypted_file.endswith('.asc') or encrypted_file.endswith('.pgp'):
decrypted_filename = encrypted_file[0:-4]
else:
decrypted_filename = encrypted_file + '.decrypt' # if it was a file without a known encrypted file type, add the .decrypt suffix
# determine whether file overwrite will take place with the decrypted file
skip_file = False # flag that indicates this file should not be encrypted
created_tmp_files = False
if not use_standard_output: # if not writing a file, no need to check for overwrite
if file_exists(decrypted_filename):
if use_file_overwrite: # rename the existing file to temp file which will be erased or replaced (on decryption failures) below
tmp_filename = decrypted_filename + '.tmp'
os.rename(decrypted_filename, tmp_filename)
created_tmp_files = True
else:
stdout("The file path '" + decrypted_filename + "' already exists. This file was not decrypted.")
skip_file = True
# begin decryption
if not skip_file:
if use_standard_output: # using --quiet flag to suppress stdout messages from gpg, just want the file data in stdout stream
system_command = "gpg --batch --quiet --passphrase " + quote(passphrase) + " -d " + quote(encrypted_file)
successful_execution = execute(system_command) # use naked execute function to directly push to stdout, rather than return stdout
if not successful_execution:
stderr("Unable to decrypt file '" + encrypted_file + "'", 0)
if created_tmp_files: # restore the moved tmp file to original if decrypt failed
tmp_filename = decrypted_filename + '.tmp'
if file_exists(tmp_filename):
os.rename(tmp_filename, decrypted_filename)
else: # decryption successful but we are in stdout flag so do not include any other output from decrypto
pass
else:
system_command = "gpg --batch -o " + quote(decrypted_filename) + " --passphrase " + quote(passphrase) + " -d " + quote(encrypted_file)
response = muterun(system_command)
if response.exitcode == 0:
stdout("'" + encrypted_file + "' decrypted to '" + decrypted_filename + "'")
else: # failed decryption
if created_tmp_files: # restore the moved tmp file to original if decrypt failed
tmp_filename = decrypted_filename + '.tmp'
if file_exists(tmp_filename):
os.rename(tmp_filename, decrypted_filename)
# report the error
stderr(response.stderr)
stderr("Decryption failed for " + encrypted_file)
# cleanup: remove the tmp file
if created_tmp_files:
tmp_filename = decrypted_filename + '.tmp'
if file_exists(tmp_filename):
os.remove(tmp_filename)
# untar/extract any detected archive file(s)
if untar_archives is True:
if decrypted_filename.endswith('.tar') and tarfile.is_tarfile(decrypted_filename):
untar_path_tuple = os.path.split(decrypted_filename)
untar_path = untar_path_tuple[0]
if use_file_overwrite:
with tarfile.open(decrypted_filename) as tar:
if len(untar_path) > 0:
tar.extractall(path=untar_path) # use dir path from the decrypted_filename if not CWD
stdout("'" + decrypted_filename + "' unpacked in the directory path '" + untar_path + "'")
else:
tar.extractall() # else use CWD
stdout("'" + decrypted_filename + "' unpacked in the current working directory")
else:
with tarfile.TarFile(decrypted_filename, 'r', errorlevel=1) as tar:
for tarinfo in tar:
t_file = tarinfo.name
if len(untar_path) > 0:
t_file_path = os.path.join(untar_path, t_file)
else:
t_file_path = t_file
if not os.path.exists(t_file_path):
try:
if len(untar_path) > 0:
tar.extract(t_file, path=untar_path) # write to the appropriate dir
else:
tar.extract(t_file) # write to CWD
except IOError as e:
stderr(
"Failed to unpack the file '" + t_file_path + "' [" + str(
e) + "]")
elif is_dir(t_file_path):
pass # do nothing if it exists and is a directory, no need to warn
else: # it is a file and it already exists, provide user error message
stderr(
"Failed to unpack the file '" + t_file_path + "'. File already exists. Use the --overwrite flag to replace existing files.")
# remove the decrypted tar archive file
os.remove(decrypted_filename)
# overwrite the entered passphrases after file decryption is complete for all files
passphrase = ""
passphrase_confirm = ""
# add a short pause to hinder brute force pexpect style password attacks with decrypto
sleep(0.2) # 200ms pause
else: # passphrases did not match
passphrase = ""
passphrase_confirm = ""
stderr("The passphrases did not match. Please enter your command again.")
sys.exit(1)
elif c.argc == 1:
# simple single file or directory processing with default settings
path = c.arg0
if file_exists(path): # SINGLE FILE
check_existing_file = False # check for a file with the name of new decrypted filename in the directory
if path.endswith('.crypt'):
decrypted_filename = path[0:-6] # remove the .crypt suffix
check_existing_file = True
elif path.endswith('.gpg') or path.endswith('.pgp') or path.endswith('.asc'):
decrypted_filename = path[0:-4]
check_existing_file = True
else:
decrypted_filename = path + ".decrypt" # if there is not a standard file type, then add a .decrypt suffix to the decrypted file name
stdout("Could not confirm that the requested file is encrypted based upon the file type. Attempting decryption. Keep your fingers crossed...")
# confirm that the decrypted path does not already exist, if so abort with warning message to user
if check_existing_file is True:
if file_exists(decrypted_filename):
stderr("Your file will be decrypted to '" + decrypted_filename + "' and this file path already exists. Please move the file or use the --overwrite option with your command if you intend to replace the current file.")
sys.exit(1)
# get passphrase used to symmetrically decrypt the file
passphrase = getpass.getpass("Please enter your passphrase: ")
if len(passphrase) == 0: # confirm that user entered a passphrase
stderr("You did not enter a passphrase. Please repeat your command and try again.")
sys.exit(1)
passphrase_confirm = getpass.getpass("Please enter your passphrase again: ")
# confirm that the passphrases match
if passphrase == passphrase_confirm:
system_command = "gpg --batch -o " + quote(decrypted_filename) + " --passphrase " + quote(passphrase) + " -d " + quote(path)
response = muterun(system_command)
if response.exitcode == 0:
# unpack tar archive generated from the decryption, if present
if decrypted_filename.endswith('.tar') and tarfile.is_tarfile(decrypted_filename):
untar_path_tuple = os.path.split(decrypted_filename)
untar_path = untar_path_tuple[0]
with tarfile.TarFile(decrypted_filename, 'r', errorlevel=1) as tar:
for tarinfo in tar:
t_file = tarinfo.name
if len(untar_path) > 0:
t_file_path = os.path.join(untar_path, t_file)
else:
t_file_path = t_file
if not os.path.exists(t_file_path):
try:
if len(untar_path) > 0:
tar.extract(t_file, path=untar_path) # write to the appropriate dir
else:
tar.extract(t_file) # write to CWD
except IOError as e:
stderr("Failed to unpack the file '" + t_file_path + "' [" + str(e) + "]")
elif is_dir(t_file_path):
pass # do nothing if it exists and is a directory, no need to warn
else: # it is a file and it already exists, provide user error message
stderr("Failed to unpack the file '" + t_file_path + "'. File already exists. Use the --overwrite flag to replace existing files.")
# remove the decrypted tar archive
os.remove(decrypted_filename)
stdout("Decryption complete")
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
sys.exit(0)
else:
stderr(response.stderr)
stderr("Decryption failed")
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
# add a short pause to hinder brute force pexpect style password attacks with decrypto
sleep(0.2) # 200ms pause
sys.exit(1)
else:
stderr("The passphrases did not match. Please enter your command again.")
sys.exit(1)
elif dir_exists(path): # SINGLE DIRECTORY
dirty_directory_file_list = list_all_files(path)
directory_file_list = [x for x in dirty_directory_file_list if (x.endswith('.crypt') or x.endswith('.gpg') or x.endswith('.pgp') or x.endswith('.asc'))]
# if there are no encrypted files found, warn and abort
if len(directory_file_list) == 0:
stderr("There are no encrypted files in the directory")
sys.exit(1)
# prompt for the passphrase
passphrase = getpass.getpass("Please enter your passphrase: ")
if len(passphrase) == 0: # confirm that user entered a passphrase
stderr("You did not enter a passphrase. Please repeat your command and try again.")
sys.exit(1)
passphrase_confirm = getpass.getpass("Please enter your passphrase again: ")
if passphrase == passphrase_confirm:
# decrypt all of the encypted files in the directory
for filepath in directory_file_list:
absolute_filepath = make_path(path, filepath) # combine the directory path and file name into absolute path
# remove file suffix from the decrypted file path that writes to disk
if absolute_filepath.endswith('.crypt'):
decrypted_filepath = absolute_filepath[0:-6] # remove the .crypt suffix
elif absolute_filepath.endswith('.gpg') or absolute_filepath.endswith('.pgp') or absolute_filepath.endswith('.asc'):
decrypted_filepath = absolute_filepath[0:-4]
# confirm that the file does not already exist
if file_exists(decrypted_filepath):
stdout("The file path '" + decrypted_filepath + "' already exists. This file was not decrypted.")
else:
system_command = "gpg --batch -o " + quote(decrypted_filepath) + " --passphrase " + quote(passphrase) + " -d " + quote(absolute_filepath)
response = muterun(system_command)
if response.exitcode == 0:
stdout("'" + absolute_filepath + "' decrypted to '" + decrypted_filepath + "'")
else:
stderr(response.stderr)
stderr("Decryption failed for " + absolute_filepath)
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
# add a short pause to hinder brute force pexpect style password attacks with decrypto
sleep(0.2) # 200ms pause
else:
# overwrite user entered passphrases
passphrase = ""
passphrase_confirm = ""
stderr("The passphrases did not match. Please enter your command again.")
sys.exit(1)
else:
# error message, not a file or directory. user entry error
stderr("The path that you entered does not appear to be an existing file or directory. Please try again.")
sys.exit(1)
# ------------------------------------------------------------------------------------------
# [ DEFAULT MESSAGE FOR MATCH FAILURE ]
# Message to provide to the user when all above conditional logic fails to meet a true condition
# ------------------------------------------------------------------------------------------
else:
print("Could not complete your request. Please try again.")
sys.exit(1)
if __name__ == '__main__':
main()

@ -0,0 +1,167 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from Naked.toolshed.shell import muterun
from Naked.toolshed.system import file_size, stdout, stderr
from shellescape import quote
# ------------------------------------------------------------------------------
# Cryptor class
# performs gpg encryption of one or more files
# ------------------------------------------------------------------------------
class Cryptor(object):
"""performs gpg encryption of one or more files"""
def __init__(self, passphrase):
self.command_default = "gpg -z 1 --batch --force-mdc --cipher-algo AES256 -o "
self.command_nocompress = "gpg -z 0 --batch --force-mdc --cipher-algo AES256 -o "
self.command_maxcompress = "gpg -z 7 --batch --force-mdc --cipher-algo AES256 -o "
self.command_default_armored = "gpg -z 1 --armor --batch --force-mdc --cipher-algo AES256 -o "
self.command_nocompress_armored = "gpg -z 0 --armor --batch --force-mdc --cipher-algo AES256 -o "
self.command_maxcompress_armored = "gpg -z 7 --armor --batch --force-mdc --cipher-algo AES256 -o "
self.passphrase = passphrase
self.common_binaries = set(['.7z', '.gz', '.aac', '.app', '.avi', '.azw', '.bz2', '.deb', '.doc', '.dmg', '.exe', '.flv', '.gif', '.jar', '.jpg', '.mov', '.mp3', '.mp4', '.odt', '.oga', '.ogg', '.ogm', '.pdf', '.pkg', '.png', '.ppt', '.pps', '.psd', '.rar', '.rpm', '.tar', '.tif', '.wav', '.wma', '.wmv', '.xls', '.zip', '.aiff', '.docx', '.epub', '.flac', '.mpeg', '.jpeg', '.pptx', '.xlsx'])
self.common_text = set(['.c', '.h', '.m', '.cc', '.js', '.pl', '.py', '.rb', '.sh', '.cpp', '.css', '.csv', '.php', '.rss', '.txt', '.xml', '.yml', '.java', '.json', '.html', '.yaml'])
# ------------------------------------------------------------------------------
# PUBLIC methods
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# encrypt_file : file encryption method
# ------------------------------------------------------------------------------
def encrypt_file(self, inpath, force_nocompress=False, force_compress=False, armored=False, checksum=False):
"""public method for single file encryption with optional compression, ASCII armored formatting, and file hash digest generation"""
if armored:
if force_compress:
command_stub = self.command_maxcompress_armored
elif force_nocompress:
command_stub = self.command_nocompress_armored
else:
if self._is_compress_filetype(inpath):
command_stub = self.command_default_armored
else:
command_stub = self.command_nocompress_armored
else:
if force_compress:
command_stub = self.command_maxcompress
elif force_nocompress:
command_stub = self.command_nocompress
else:
if self._is_compress_filetype(inpath):
command_stub = self.command_default
else:
command_stub = self.command_nocompress
encrypted_outpath = self._create_outfilepath(inpath)
system_command = command_stub + encrypted_outpath + " --passphrase " + quote(self.passphrase) + " --symmetric " + quote(inpath)
try:
response = muterun(system_command)
# check returned status code
if response.exitcode == 0:
stdout(encrypted_outpath + " was generated from " + inpath)
if checksum: # add a SHA256 hash digest of the encrypted file - requested by user --hash flag in command
from crypto.library import hash
encrypted_file_hash = hash.generate_hash(encrypted_outpath)
if len(encrypted_file_hash) == 64:
stdout("SHA256 hash digest for " + encrypted_outpath + " :")
stdout(encrypted_file_hash)
else:
stdout("Unable to generate a SHA256 hash digest for the file " + encrypted_outpath)
else:
stderr(response.stderr, 0)
stderr("Encryption failed")
sys.exit(1)
except Exception as e:
stderr("There was a problem with the execution of gpg. Encryption failed. Error: [" + str(e) + "]")
sys.exit(1)
# ------------------------------------------------------------------------------
# encrypt_files : multiple file encryption
# ------------------------------------------------------------------------------
def encrypt_files(self, file_list, force_nocompress=False, force_compress=False, armored=False, checksum=False):
"""public method for multiple file encryption with optional compression, ASCII armored formatting, and file hash digest generation"""
for the_file in file_list:
self.encrypt_file(the_file, force_nocompress, force_compress, armored, checksum)
# ------------------------------------------------------------------------------
# cleanup : overwrite the passphrase in memory
# ------------------------------------------------------------------------------
def cleanup(self):
"""public method that overwrites user passphrase in memory"""
self.passphrase = ""
# ------------------------------------------------------------------------------
# PRIVATE methods
# ------------------------------------------------------------------------------
def _create_outfilepath(self, inpath):
"""private method that generates the crypto saved file path string with a .crypt file type"""
return inpath + '.crypt'
def _is_compress_filetype(self, inpath):
"""private method that performs magic number and size check on file to determine whether to compress the file"""
# check for common file type suffixes in order to avoid the need for file reads to check magic number for binary vs. text file
if self._is_common_binary(inpath):
return False
elif self._is_common_text(inpath):
return True
else:
# files > 10kB get checked for compression (arbitrary decision to skip compression on small files)
the_file_size = file_size(inpath)
if the_file_size > 10240:
if the_file_size > 512000: # seems to be a break point at ~ 500kb where file compression offset by additional file read, so limit tests to files > 500kB
try:
system_command = "file --mime-type -b " + quote(inpath)
response = muterun(system_command)
if response.stdout[0:5] == "text/": # check for a text file mime type
return True # appropriate size, appropriate file mime type
else:
return False # appropriate size, inappropriate file mime type
except Exception:
return False
else:
return True # if file size is < 500kB, skip the additional file read and just go with compression
else:
return False # below minimum size to consider compression, do not compress
def _is_common_binary(self, inpath):
"""private method to compare file path mime type to common binary file types"""
# make local variables for the available char numbers in the suffix types to be tested
two_suffix = inpath[-3:]
three_suffix = inpath[-4:]
four_suffix = inpath[-5:]
# test for inclusion in the instance variable common_binaries (defined in __init__)
if two_suffix in self.common_binaries:
return True
elif three_suffix in self.common_binaries:
return True
elif four_suffix in self.common_binaries:
return True
else:
return False
def _is_common_text(self, inpath):
"""private method to compare file path mime type to common text file types"""
# make local variables for the available char numbers in the suffix types to be tested
one_suffix = inpath[-2:]
two_suffix = inpath[-3:]
three_suffix = inpath[-4:]
four_suffix = inpath[-5:]
# test for inclusion in the instance variable common_text (defined in __init__)
if one_suffix in self.common_text:
return True
elif two_suffix in self.common_text:
return True
elif three_suffix in self.common_text:
return True
elif four_suffix in self.common_text:
return True
else:
return False

@ -0,0 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import hashlib
from Naked.toolshed.file import FileReader
# ------------------------------------------------------------------------------
# PUBLIC
# ------------------------------------------------------------------------------
def generate_hash(filepath):
"""Public function that reads a local file and generates a SHA256 hash digest for it"""
fr = FileReader(filepath)
data = fr.read_bin()
return _calculate_sha256(data)
# ------------------------------------------------------------------------------
# PRIVATE
# ------------------------------------------------------------------------------
def _calculate_sha256(binary_string):
"""Private function that calculates a SHA256 hash digest for a binary string argument"""
return hashlib.sha256(binary_string).hexdigest()

@ -0,0 +1,45 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import tarfile
from Naked.toolshed.system import stderr, dir_exists, file_exists
# ------------------------------------------------------------------------------
# PUBLIC
# ------------------------------------------------------------------------------
def generate_tar_files(directory_list):
"""Public function that reads a list of local directories and generates tar archives from them"""
tar_file_list = []
for directory in directory_list:
if dir_exists(directory):
_generate_tar(directory) # create the tar archive
tar_file_list.append(directory + '.tar') # append the tar archive filename to the returned tar_file_list list
else:
stderr("The directory '" + directory + "' does not exist and a tar archive could not be created from it.", exit=1)
return tar_file_list
def remove_tar_files(file_list):
"""Public function that removes temporary tar archive files in a local directory"""
for f in file_list:
if file_exists(f) and f.endswith('.tar'):
os.remove(f) # remove any tar files in the list, if it does not appear to be a tar file, leave it alone
# ------------------------------------------------------------------------------
# PRIVATE
# ------------------------------------------------------------------------------
def _generate_tar(dir_path):
"""Private function that reads a local directory and generates a tar archive from it"""
try:
with tarfile.open(dir_path + '.tar', 'w') as tar:
tar.add(dir_path)
except tarfile.TarError as e:
stderr("Error: tar archive creation failed [" + str(e) + "]", exit=1)

@ -0,0 +1,104 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
# Application Name
# ------------------------------------------------------------------------------
app_name = 'crypto'
# ------------------------------------------------------------------------------
# Version Number
# ------------------------------------------------------------------------------
major_version = "1"
minor_version = "4"
patch_version = "1"
# ------------------------------------------------------------------------------
# Debug Flag (switch to False for production release code)
# ------------------------------------------------------------------------------
debug = False
# ------------------------------------------------------------------------------
# Usage String
# ------------------------------------------------------------------------------
usage = """
Encrypt by explicit file path:
------------------------------
crypto <options> [file path] <file path 2...>
Encrypt all top level files in directory:
-----------------------------------------
crypto <options> [directory path] <directory path 2...>
Create a tar archive from directory and encrypt the archive:
-----------------------------------------------------------
crypto --tar [directory path] <directory path 2...>
Decrypt by explicit file path:
------------------------------
decrypto <options> [file path] <file path 2...>
Decrypt all top level encrypted files in directory:
---------------------------------------------------
decrypto <options> [directory path] <directory path 2...>
Enter `crypto --help` or `decrypto --help` to view the available options.
"""
# ------------------------------------------------------------------------------
# Help String
# ------------------------------------------------------------------------------
help = """
-------------------------------------------------
crypto
Simple symmetric GPG file encryption
Copyright 2015 Christopher Simpkins
MIT license
Source: https://github.com/chrissimpkins/crypto
Docs: https://chrissimpkins.github.io/crypto/
-------------------------------------------------
ABOUT
crypto provides a simple interface to symmetric Gnu Privacy Guard (gpg) encryption and decryption for one or more files. gpg must be installed on your system in order to use the crypto and decrypto executables.
USAGE
ENCRYPTION
crypto <options> [file path] <file path...>
crypto <options> [directory path] <directory path...>
DECRYPTION
decrypto <options> [file path] <file path...>
decrypto <options> [directory path] <directory path...>
CRYPTO OPTIONS
--armor | -a Use a portable ASCII armored encryption format
--hash Generate SHA256 hash digest of encrypted file(s)
--space Favor reduced file size over encryption speed
--speed Favor encryption speed over reduced file size
--tar Create tar archive of directory of files before encryption
DECRYPTO OPTIONS
--nountar Do not automatically unpack decrypted tar archives
--overwrite | -o Overwrite an existing file with the decrypted file
--stdout | -s Print file contents to the standard output stream
OTHER OPTIONS
--help | -h Display crypto and decrypto help
--usage Display crypto and decrypto usage
--version | -v Display version number
DESCRIPTION
Use one or more explicit file path arguments to encrypt or decrypt the file(s). crypto and decrypto will attempt to encrypt or decrypt (respectively) any explicit filepaths that you include irrespective of the file type. Encrypted files are generated on the path '<original_filepath>.crypt'. The original file is not modified or removed by crypto.
Use one or more directory arguments with the crypto executable to encrypt all files in the top level of each directory with the same passphrase. Previously encrypted files with a '.crypt' file type will not be generated again in a directory. Remove them before you run the command if you intend to repeat encryption with a file.
Use one or more directory arguments with decrypto to decrypt all .crypt, .gpg, .asc, and .pgp files in the top level of each directory. decrypto automatically unpacks decrypted tar archives.
Encryption is performed with the AES256 cipher algorithm. Decryption will take place with any cipher algorithm that your version of gpg supports.
"""

@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.0.41 Version: 1.0.42
Summary: First open source RPA platform for business Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov Author: Ivan Maslov
@ -18,6 +18,7 @@ Requires-Dist: pillow (>=6.0.0)
Requires-Dist: keyboard (>=0.13.3) Requires-Dist: keyboard (>=0.13.3)
Requires-Dist: pyautogui (>=0.9.44) Requires-Dist: pyautogui (>=0.9.44)
Requires-Dist: pywin32 (>=224) Requires-Dist: pywin32 (>=224)
Requires-Dist: crypto (>=1.4.1)
# OpenRPA # OpenRPA
First open source RPA platform for business is released! First open source RPA platform for business is released!

@ -1,8 +1,8 @@
pyOpenRPA-1.0.41.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.0.42.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.41.dist-info/METADATA,sha256=Yp_YJ3c0_9M4JNzepyJrPqDDp4K4GdCIF98pWtuhLu4,3510 pyOpenRPA-1.0.42.dist-info/METADATA,sha256=Spesv5ub8aq5ymKhq_1kDDFQ2lrCrTwXfF8PakH7OO8,3542
pyOpenRPA-1.0.41.dist-info/RECORD,, pyOpenRPA-1.0.42.dist-info/RECORD,,
pyOpenRPA-1.0.41.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.0.42.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.41.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.0.42.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436 pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436
pyOpenRPA/Orchestrator/Processor.py,sha256=kmGNIqe6AZMSrzCt1QlonEy58ecFeLunjo8AeRMsufU,11091 pyOpenRPA/Orchestrator/Processor.py,sha256=kmGNIqe6AZMSrzCt1QlonEy58ecFeLunjo8AeRMsufU,11091
pyOpenRPA/Orchestrator/Server.py,sha256=s1ujCuRX6YxRllqPn541Df4pJP7kOexiS3RIuoT4nyE,22053 pyOpenRPA/Orchestrator/Server.py,sha256=s1ujCuRX6YxRllqPn541Df4pJP7kOexiS3RIuoT4nyE,22053
@ -265,7 +265,17 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/Crypter.py,sha256=VRrE5-oQxQtvMEPHM1lMXp2CKnceNBmIWJnsJoJkaVE,3616
pyOpenRPA/Tools/SafeSource/DistrCreate.py,sha256=-_8BTle57LBKVknnB_3af-LghxrRmRGfRNu08CLNIvY,3232
pyOpenRPA/Tools/SafeSource/DistrRun.py,sha256=TH4uExbufnOubBrTiO8Ccw00E5K6zaJ59-vApSxQ0iY,6661
pyOpenRPA/Tools/SafeSource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/SafeSource/__main__.py,sha256=g5aYWnuUZoM2jDX2mSIl9tRAJg05tu5VxD2rGJWcACg,649
pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrRun.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=lQ3_677Rja_PqcurcKK5fdhTpkzhXA866JG0Ke-ttxU,175 pyOpenRPA/__init__.py,sha256=9w2hSRgGrWKyQb3T_j71u7VoYGZsrTZz189nKtqEmOQ,175
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save