diff --git a/.appveyor.yml b/.appveyor.yml index 29fb998..1d35fa4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.{build} +version: 1.1.{build} branches: only: - master @@ -6,8 +6,8 @@ branches: skip_tags: true max_jobs: 1 image: -- Visual Studio 2017 -- Visual Studio 2015 +- Visual Studio 2022 +- Visual Studio 2019 clone_depth: 50 init: - cmd: >- diff --git a/.circleci/config.yml b/.circleci/config.yml index 8471a30..c1ce0f4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,9 +2,9 @@ version: 2 jobs: build: docker: - - image: circleci/python:3.6.1 - image: circleci/python:3.7 - image: circleci/python:3.8 + - image: circleci/python:3.9 environment: CI: cicleci DEBIAN_FRONTEND: noninteractive @@ -41,9 +41,9 @@ jobs: test: docker: - - image: circleci/python:3.6.1 - image: circleci/python:3.7 - image: circleci/python:3.8 + - image: circleci/python:3.9 parallelism: 2 environment: CI: cicleci @@ -88,9 +88,9 @@ jobs: pytest: docker: - - image: circleci/python:3.6.1 - image: circleci/python:3.7 - image: circleci/python:3.8 + - image: circleci/python:3.9 parallelism: 2 environment: CI: cicleci @@ -147,7 +147,7 @@ jobs: lint: docker: - - image: circleci/python:3.6.1 + - image: circleci/python:3.8 environment: CI: cicleci DEBIAN_FRONTEND: noninteractive diff --git a/.gitignore b/.gitignore index 5d7e4e3..47b603a 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ coverage.xml codecov_env *,cover .hypothesis/ +test-reports/* # Translations *.mo diff --git a/LICENSE.md b/LICENSE.md index a8f8ee4..3ee50db 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ License - MIT -Copyright (c) 2017-2020 Mr. Walls +Copyright (c) 2017-2022 Mr. Walls THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, diff --git a/Makefile b/Makefile index 1548c94..01ba15f 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,7 @@ PHONY: must_be_root cleanup build: $(QUIET)$(ECHO) "No need to build. Try make -f Makefile install" + $(QUIET)$(MAKE) -s -C ./docs/ -f Makefile text 2>/dev/null || true init: $(QUIET)$(ECHO) "$@: Done." @@ -84,7 +85,7 @@ purge: clean uninstall test: cleanup $(QUIET)coverage run -p --source=pythonrepo -m unittest discover --verbose -s ./tests -t ./ || python3 -m unittest discover --verbose -s ./tests -t ./ || python -m unittest discover --verbose -s ./tests -t ./ || DO_FAIL=exit 2 ; $(QUIET)coverage combine 2>/dev/null || true - $(QUIET)coverage report --include=pythonrepo* 2>/dev/null || true + $(QUIET)coverage report -m --include=pythonrepo* 2>/dev/null || true $(QUIET)$(DO_FAIL); $(QUIET)$(ECHO) "$@: Done." diff --git a/docs/conf.py b/docs/conf.py index b8aaf7e..1437135 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,7 +32,7 @@ templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = '.md' # The encoding of source files. # source_encoding = 'utf-8-sig' @@ -51,7 +51,7 @@ # The short X.Y version. version = 'v1.1' # The full version, including alpha/beta/rc tags. -release = 'v1.1.1' +release = 'v1.1.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/index.rst b/docs/index.md similarity index 100% rename from docs/index.rst rename to docs/index.md diff --git a/python-repo.xcworkspace/contents.xcworkspacedata b/python-repo.xcworkspace/contents.xcworkspacedata index ca3329e..dc6fdb0 100644 --- a/python-repo.xcworkspace/contents.xcworkspacedata +++ b/python-repo.xcworkspace/contents.xcworkspacedata @@ -1,7 +1,5 @@ - - + + diff --git a/pythonrepo/__init__.py b/pythonrepo/__init__.py index 51b0c57..d6b3976 100644 --- a/pythonrepo/__init__.py +++ b/pythonrepo/__init__.py @@ -2,7 +2,7 @@ # Python Repo Template # .................................. -# Copyright (c) 2017-2019, Kendrick Walls +# Copyright (c) 2017-2022, Kendrick Walls # .................................. # Licensed under MIT (the "License"); # you may not use this file except in compliance with the License. @@ -16,37 +16,27 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Python Repo.""" -__version__ = """1.1.1""" -"""This is version 1.1.1 of pythonrepo Template""" +__module__ = """pythonrepo""" +"""This is pythonrepo module Template.""" + + +__version__ = """1.1.4""" +"""This is version 1.1.4 of pythonrepo Template""" try: import sys import os - if 'pythonrepo' in __file__: + if str(__module__) in __file__: __parentPath = os.path.join( os.path.dirname(__file__), '..' ) sys.path.insert(0, os.path.abspath(__parentPath)) -except Exception as ImportErr: - print(str(type(ImportErr))) - print(str(ImportErr)) - print(str((ImportErr.args))) - ImportErr = None - del ImportErr - raise ImportError(str("pythonrepo Failed to Import")) - - -try: - from . import pythonrepo as pythonrepo -except Exception as importErr: - del importErr - import pythonrepo.pythonrepo as pythonrepo - - -if __name__ in '__main__': - if pythonrepo.__name__ is None: - raise ImportError(str("Failed to open pythonrepo")) - pythonrepo.main(sys.argv[1:]) - exit(0) +except Exception as err: + baton = ImportError(err, str("[CWE-758] Module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = err + raise baton diff --git a/pythonrepo/pythonrepo.py b/pythonrepo/pythonrepo.py index bfb2846..1e25716 100644 --- a/pythonrepo/pythonrepo.py +++ b/pythonrepo/pythonrepo.py @@ -3,7 +3,7 @@ # Python Repo Template # .................................. -# Copyright (c) 2017-2019, Kendrick Walls +# Copyright (c) 2017-2022, Kendrick Walls # .................................. # Licensed under MIT (the "License"); # you may not use this file except in compliance with the License. @@ -18,23 +18,28 @@ # limitations under the License. +__module__ = """pythonrepo.pythonrepo""" +"""This is pythonrepo component Template.""" + + try: - import sys + from . import sys import argparse except Exception as err: - # Show Error Info - print(str(type(err))) - print(str(err)) - print(str(err.args)) - print(str("")) - # Clean up Error - err = None - del(err) + # Collect Error Info + baton = ImportError(err, str("[CWE-758] Module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = err # Throw more relevant Error - raise ImportError(str("Error Importing Python")) + raise baton + + +from . import __version__ +"""The version of this program.""" -__prog__ = str("""pythonrepo""") +__prog__ = str(__module__) """The name of this program is PythonRepo""" @@ -50,10 +55,6 @@ """Contains the short epilog of the program CLI help text.""" -__version__ = """1.1.1""" -"""The version of this program.""" - - # Add your functions here @@ -96,16 +97,8 @@ def parseArgs(arguments=None): return parser.parse_known_args(arguments) -def __checkToolArgs(args=None): - """Handles None case for arguments as a helper function.""" - if args is None: - args = [None] - return args - - -def useTool(tool, arguments=None): +def useTool(tool, *arguments): """Handler for launching the functions.""" - arguments = __checkToolArgs(arguments) if (tool is not None) and (tool in TASK_OPTIONS.keys()): try: # print(str("launching: " + tool)) @@ -118,11 +111,11 @@ def useTool(tool, arguments=None): return None -def main(argv=None): +def main(*argv): """The Main Event.""" try: try: - args, extra = parseArgs(argv) + args, extra = parseArgs(*argv) service_cmd = args.some_task useTool(service_cmd, extra) except Exception: @@ -139,6 +132,7 @@ def main(argv=None): exit(0) -if __name__ == '__main__': +if __name__ in '__main__': + # deepsource overlooks the readability of "if main" type code here. (See PTC-W0048) if (sys.argv is not None) and (len(sys.argv) >= 1): main(sys.argv[1:]) diff --git a/setup.cfg b/setup.cfg index bacc4a3..458a068 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pythonrepo -version = 1.1.3 +version = 1.1.4 author = Mr. Walls author-email = reactive-firewall@users.noreply.github.com summary = python-repo template @@ -13,6 +13,8 @@ classifiers = Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 3 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.5 diff --git a/tests/__init__.py b/tests/__init__.py index a0a4ea7..6ad829e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -2,7 +2,7 @@ # Python Repo Template # .................................. -# Copyright (c) 2017-2019, Kendrick Walls +# Copyright (c) 2017-2022, Kendrick Walls # .................................. # Licensed under MIT (the "License"); # you may not use this file except in compliance with the License. @@ -16,6 +16,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Python Repo Testing Module.""" + +__module__ = """tests""" +"""This is pythonrepo testing module Template.""" + + try: try: import sys @@ -30,6 +36,9 @@ ImportErr = None del ImportErr raise ImportError(str("Test module failed completely.")) + from tests import context as context + if context.__name__ is None: + raise ImportError(str("Test module failed to import even the context framework.")) from tests import profiling as profiling if profiling.__name__ is None: raise ImportError(str("Test module failed to import even the profiling framework.")) @@ -37,11 +46,8 @@ if test_basic.__name__ is None: raise ImportError(str("Test module failed to import even the basic tests.")) except Exception as badErr: - print(str('')) - print(str(type(badErr))) - print(str(badErr)) - print(str((badErr.args))) - print(str('')) - badErr = None - del badErr - exit(0) + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton diff --git a/tests/context.py b/tests/context.py index eded610..f8c79ac 100644 --- a/tests/context.py +++ b/tests/context.py @@ -2,7 +2,7 @@ # Python Repo Template # .................................. -# Copyright (c) 2017-2019, Kendrick Walls +# Copyright (c) 2017-2022, Kendrick Walls # .................................. # Licensed under MIT (the "License"); # you may not use this file except in compliance with the License. @@ -17,26 +17,30 @@ # limitations under the License. +__module__ = """tests.context""" +"""This is pythonrepo testing module Template.""" + + try: import sys import os if 'pythonrepo' in __file__: sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) -except Exception as ImportErr: - print(str(type(ImportErr))) - print(str(ImportErr)) - print(str((ImportErr.args))) - ImportErr = None - del ImportErr - raise ImportError("Python Repo Failed to Import") +except Exception as badErr: + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton try: import pythonrepo as pythonrepo if pythonrepo.__name__ is None: raise ImportError("Failed to import pythonrepo.") -except Exception as importErr: - importErr = None - del importErr - raise ImportError("Test module failed to load pythonrepo for test.") - exit(0) +except Exception as badErr: + baton = ImportError(badErr, str("[CWE-758] Test module failed to load pythonrepo for test.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton diff --git a/tests/profiling.py b/tests/profiling.py index 3c56391..08b0b87 100644 --- a/tests/profiling.py +++ b/tests/profiling.py @@ -1,9 +1,9 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- -# Python Repo Template +# Python Test Repo Template # .................................. -# Copyright (c) 2017-2019, Kendrick Walls +# Copyright (c) 2017-2022, Kendrick Walls # .................................. # Licensed under MIT (the "License"); # you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ # limitations under the License. -# Third-party Acknowlegement: +# Third-party Acknowledgement: # .......................................... # Some code (namely: class timewith, @do_cprofile, @do_line_profile) was modified/derived from: # https://github.com/zapier/profiling-python-like-a-boss/tree/1ab93a1154 @@ -29,37 +29,85 @@ # NO ASSOCIATION +__module__ = """tests.profiling""" +"""This is pythonrepo testing module Template.""" + + try: - import os import sys + if sys.__name__ is None: # pragma: no branch + raise ImportError("[CWE-758] OMG! we could not import sys! ABORT. ABORT.") +except Exception as badErr: # pragma: no branch + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton + + +try: + if 'os' not in sys.modules: + import os + else: # pragma: no branch + os = sys.modules["""os"""] +except Exception as badErr: # pragma: no branch + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton + + +try: + if 'functools' not in sys.modules: + import functools + else: # pragma: no branch + functools = sys.modules["""functools"""] +except Exception as badErr: # pragma: no branch + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton + + +try: import time - import cProfile - for keyModule in [os, sys, time, cProfile]: - if keyModule.__name__ is None: - raise NotImplementedError( - str("OMG! We could not import the {}!").format( - str(keyModule) - ) - ) -except Exception as err: - raise ImportError(err) + if time.__name__ is None: # pragma: no branch + raise NotImplementedError("[CWE-440] We could not import time. Are we in the speed-force!") +except Exception as badErr: # pragma: no branch + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton + + +try: + if 'cProfile' not in sys.modules: + import cProfile + else: # pragma: no branch + cProfile = sys.modules["""cProfile"""] +except Exception as badErr: # pragma: no branch + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton try: try: sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), str('..')))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), str('.')))) - except Exception as ImportErr: - print(str('')) - print(str(type(ImportErr))) - print(str(ImportErr)) - print(str((ImportErr.args))) - print(str('')) - ImportErr = None - del ImportErr - raise ImportError(str("Profile module failed completely.")) -except Exception: - raise ImportError("Failed to import test profiling") + except Exception as ImportErr: # pragma: no branch + raise ImportError(ImportErr, str("[CWE-758] Profile module failed completely.")) +except Exception as badErr: # pragma: no branch + baton = ImportError(badErr, str("[CWE-758] Test module failed completely.")) + baton.module = __module__ + baton.path = __file__ + baton.__cause__ = badErr + raise baton class timewith(): @@ -86,15 +134,41 @@ def __enter__(self): def __exit__(self, type, value, traceback): self.checkpoint(str("finished")) + pass def do_time_profile(func, timer_name="time_profile"): - """Runs a function with a timer""" - import functools + """Run a function with a timer. + + Time Testing: + First some test fixtures: + + >>> import tests.context as context + >>> from context import profiling as profiling + >>> + + Testcase 0: test the time_profile. + + >>> def doWork(): + ... \"""Does some work.\""" + ... for i in range(0, 42): + ... print(str("Do Task {}").format(int(i))) + >>> + >>> profiling.do_time_profile( + ... doWork, + ... timer_name=str("work time test") + ... )() #doctest: -DONT_ACCEPT_BLANKLINE, +ELLIPSIS + work...Start Timer... + ...Do Task... + work...Stop Timer... + work...took ... seconds + >>> + + """ @functools.wraps(func) def timer_profile_func(*args, **kwargs): - """Wraps a function in timewith()""" + """Wraps a function in timewith() function.""" theOutput = None with timewith(timer_name) as timer: timer.checkpoint(str("Start Timer")) @@ -106,8 +180,39 @@ def timer_profile_func(*args, **kwargs): def do_cprofile(func): - """use built-in profiler to profile.""" + """Use built-in profiler to profile. + + Time Testing: + + First some test fixtures: + + >>> import tests.context as context + >>> from context import profiling as profiling + >>> + + Testcase 0: test the time_profile. + + >>> def doWork(): + ... \"""Does some work.\""" + ... for i in range(0, 42): + ... print(str("Do Task {}").format(int(i))) + >>> + >>> profiling.do_cprofile( + ... doWork + ... )() #doctest: -DONT_ACCEPT_BLANKLINE, +ELLIPSIS + Do Task 0...Do Task 10...Do Task 20...Do Task 30...Do Task 40... + ...function calls in ... seconds...Ordered by: standard name... + ...ncalls tottime percall cumtime percall filename:lineno(function)... + ...<...>:1(doWork)...{built-in method builtins.print}... + + + >>> + + + """ + @functools.wraps(func) def profiled_func(*args, **kwargs): + """Wraps a function in profile.enable/disable() functions.""" profile = cProfile.Profile() try: profile.enable() @@ -122,7 +227,7 @@ def profiled_func(*args, **kwargs): try: # noqa from line_profiler import LineProfiler - def do_profile(follow=None): + def do_profile(follow=None): # pragma: no cover if follow is None: follow = [] @@ -140,9 +245,9 @@ def profiled_func(*args, **kwargs): return profiled_func return inner -except ImportError: +except ImportError: # pragma: no cover def do_profile(follow=None): - "Helpful if you accidentally leave in production!" + """Helpful if you accidentally leave in production!""" if follow is None: follow = [] @@ -153,16 +258,15 @@ def nothing(*args, **kwargs): return inner -def main(argv=None): - """The Main Event makes no sense to remediation.""" +def main(*argv): # pragma: no cover + """The Main Event makes no sense to profiling.""" raise NotImplementedError("CRITICAL - test profiling main() not implemented. yet?") -if __name__ in '__main__': +if __name__ in '__main__': # pragma: no cover exitcode = 3 try: exitcode = main(sys.argv[1:]) finally: exit(exitcode) - diff --git a/tests/test_basic.py b/tests/test_basic.py index 0b290c8..f76f54f 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -47,7 +47,7 @@ def test_syntax(self): print(str(type(impErr))) print(str(impErr)) theResult = False - assert theResult + self.assertTrue(theResult) def test_the_help_command(self): """Test case for backend library.""" @@ -64,22 +64,25 @@ def test_the_help_command(self): theResult = True except Exception: theResult = False - assert theResult + self.assertTrue(theResult) def test_corner_case_example(self): """Example Test case for bad input directly into function.""" - theResult = False + theResult = True try: from .context import pythonrepo if pythonrepo.__name__ is None: theResult = False - from pythonrepo import pythonrepo as pythonrepo - self.assertIsNone(pythonrepo.useTool(None)) - self.assertIsNone(pythonrepo.useTool("JunkInput")) - theResult = True + from pythonrepo import pythonrepo as _pythonrepo + self.assertIsNone(_pythonrepo.useTool(None, None), """None, None Failed""") + self.assertIsNone(_pythonrepo.useTool(None, []), """None, [] Failed""") + self.assertIsNone(_pythonrepo.useTool(tool=None), """None Failed""") + self.assertIsNone(_pythonrepo.useTool("JunkInput"), """junk Failed""") + self.assertTrue(theResult) except Exception: + self.fail("""Test Failed""") theResult = False - assert theResult + self.assertTrue(theResult) def test_new_tests(self): """Try adding new tests.""" diff --git a/tests/test_usage.py b/tests/test_usage.py index 58481a1..9dfe1eb 100644 --- a/tests/test_usage.py +++ b/tests/test_usage.py @@ -52,7 +52,7 @@ def getPythonCommand(): def buildPythonCommand(args=None): - """Function for building backend subprocess command line""" + """Function for building backend subprocess command line.""" theArgs = args # you need to change this to the name of your project __project__ = str("pythonrepo") @@ -80,7 +80,7 @@ def buildPythonCommand(args=None): def checkPythonCommand(args=None, stderr=None): - """Function for backend subprocess check_output command like testing with coverage support""" + """Function for backend subprocess check_output command like testing with coverage support.""" theOutput = None try: taintArgs = buildPythonCommand(args) @@ -163,11 +163,11 @@ class BasicUsageTestSuite(unittest.TestCase): """Basic functional test cases.""" def test_absolute_truth_and_meaning(self): - """Insanity Test. if ( is true ) """ - assert True + """Insanity Test. if ( is true ) usage.""" + self.assertTrue(True) def test_syntax(self): - """Test case importing code. if ( import is not None ) """ + """Test case importing code. if ( import is not None ) usage.""" theResult = False try: from .context import pythonrepo @@ -178,10 +178,10 @@ def test_syntax(self): print(str(type(impErr))) print(str(impErr)) theResult = False - assert theResult + self.assertTrue(theResult) def test_template_case(self): - """Test case template for: python -m pythonrepo.* --version """ + """Test case template for: python -m pythonrepo.* --version usage.""" theResult = False thepython = getPythonCommand() if (thepython is not None): @@ -217,10 +217,10 @@ def test_template_case(self): err = None del err theResult = False - assert theResult + self.assertTrue(theResult) def test_profile_template_case(self): - """Test case template for profiling""" + """Test case template for profiling.""" theResult = False thepython = getPythonCommand() if (thepython is not None): @@ -255,11 +255,11 @@ def test_profile_template_case(self): err = None del err theResult = False - assert theResult + self.assertTrue(theResult) @unittest.expectedFailure def test_fail_template_case(self): - """Test case template for profiling""" + """Test case template for profiling.""" theResult = False thepython = getPythonCommand() if (thepython is not None): @@ -294,11 +294,11 @@ def test_fail_template_case(self): err = None del err theResult = False - assert theResult + self.assertTrue(theResult) @unittest.expectedFailure def test_bad_template_case(self): - """Test case template for profiling""" + """Test case template for profiling.""" theResult = False thepython = getPythonCommand() if (thepython is not None): @@ -333,7 +333,7 @@ def test_bad_template_case(self): err = None del err theResult = False - assert theResult + self.assertTrue(theResult) if __name__ == '__main__':