diff --git a/.bzrignore b/.bzrignore deleted file mode 100644 index 1f4abe3..0000000 --- a/.bzrignore +++ /dev/null @@ -1,18 +0,0 @@ -./api -./build -./dist -./docs/manual.html -./docs/manual/.build/doctrees/* -./docs/manual/.build/html/* -./intelhex-* -./MANIFEST -__pycache__ -tags -fastimport.marks -fastimport.stream -wheelhouse -./.git -./.gitignore -./venv -./python.bat -./*.html diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1d106d0..0000000 --- a/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -*.egg-info -*.pyc -.bzr/* -*.~* -docs/manual.html -docs/manual/.build/doctrees/* -docs/manual/.build/html/* -venv/ -dist/ -.tox/ -MANIFEST -python.bat -NEWS.html -README.html diff --git a/AUTHORS.rst b/AUTHORS.rst deleted file mode 100644 index eb1efdd..0000000 --- a/AUTHORS.rst +++ /dev/null @@ -1,30 +0,0 @@ -Author: Alexander Belchenko - -Copyright (C) Alexander Belchenko, 2005-2018 - -Special thanks to Bernhard Leiner for huge help in porting -IntelHex library to Python 3. - -Contributors: - -* Alexander Belchenko -* Alex Mueller -* Andrew Fernandes -* Bernhard Leiner -* Enoch H. Wexler -* Heiko Henkelmann -* Henrik Maier -* Masayuki Takeda -* Morgan McClure -* Nathan P. Stien -* Piotr Korowacki -* Reis Baltaoglu -* Ryan Downing -* Scott Armitage -* Stefan Schmitt -* Svein Seldal -* Theo Sbrissa -* Zachary Clifford -* "durexyl" @ GitHub -* "erki1993" @ GitHub -* "mentaal" @ GitHub diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index f75d734..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,32 +0,0 @@ -Copyright (c) 2005-2018, Alexander Belchenko -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. -* Neither the name of the author nor the names - of its contributors may be used to endorse - or promote products derived from this software - without specific prior written permission. - -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 OWNER 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. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 97193ec..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -include AUTHORS.rst -include LICENSE.txt -include NEWS.rst -include README.rst diff --git a/Makefile b/Makefile deleted file mode 100644 index cac3095..0000000 --- a/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -PYTHON := python - -all: - @echo Available targets: - @echo clean - clean build directory - @echo test - run unittest - @echo dev - install via pip as editable package - @echo apidoc - run epdoc to create API documentation - @echo wininst - Windows installer for Python - @echo docs - build docs with ReST and Sphinx - @echo wheel - build python wheel binary archive - -.PHONY: clean test epydoc wininst docs dev apidoc wheel - -clean: - $(PYTHON) setup.py clean -a - -test: - $(PYTHON) setup.py test -q - -dev: - $(PYTHON) -m pip install -e . - -apidoc: - pdoc -o docs/api --html -f intelhex - -wininst: - $(PYTHON) setup.py bdist_wininst -d. - -docs: - rst2html5.py docs/manual.txt docs/manual.html - $(MAKE) -C docs/manual html - -wheel: - $(PYTHON) -m pip wheel -w dist . diff --git a/NEWS.rst b/NEWS.rst deleted file mode 100644 index 14e7e4b..0000000 --- a/NEWS.rst +++ /dev/null @@ -1,186 +0,0 @@ -***************** -IntelHex releases -***************** - -* Added support for ``in`` operator to check if address is in HEX file. - -2.3.0 (2020-10-20) ------------------- -* Add ``IntelHex.find()`` method to find a given byte pattern. (Scott Armitage) -* API changes: ``IntelHex.segments()`` method supports new optional parameter - ``min_gap`` to allow consolidation of segments with small but existing gaps - into a single segment. Default value is 1. (Ryan Downing) -* API changes: ``IntelHex.tofile()`` now supports the optional ``byte_count`` - parameter from ``IntelHex.write_hex_file()``. Only used if ``format = hex``. - (Reis Baltaoglu) -* Fix Python 3.9 compatibility issue with 'array' module (Piotr Korowacki) -* Fix installation for Python version taking setup rather from setuptools than - distutils (Theo Sbrissa) - -2.2.1 (2018-01-30) ------------------- -* Fixes for PyPI. - -2.2 (2018-01-28) ----------------- -* API changes: ``IntelHex.write_hex_file`` method: added support for new - parameter: ``eolstyle = native | CRLF``. (Alexander Belchenko) -* API changes: ``IntelHex.write_hex_file()`` method gets new optional - parameter ``byte_count`` to specify how many bytes should be written - to each data record in output file. Default value is 16. - (patch from GitHub user erki1993) -* Unit tests: Fixed xrange overflow test for Python 2.7 on 64-bit platforms. - Use ``sys.maxint`` to ensure we trigger an exception. (Masayuki Takeda) -* Script ``hexinfo.py``: Python 3 compatibility for processing start address - dict keys. (patch from GitHub user mentaal) -* Added ``get_memory_size()`` method: approx memory footprint of IntelHex object - plus data. (Alexander Belchenko) -* Better compatibility with Python 3. (Alexander Belchenko) - -2.1 (2016-03-31) ----------------- -* API changes: added ``IntelHex.segments()`` method that returns - a list of ordered tuple objects, representing contiguous occupied data - addresses. (Andrew Fernandes) -* New command-line script ``hexinfo.py`` to print summary about hex files - contents (file name, start address, address ranges covered by the data) - in YAML format. (Andrew Fernandes) -* Better Python 3 compatibility when ``hex2bin.py`` and ``bin2hex.py`` - scripts are trying to read/write binary data from stdin or to stdout. - (GitHub issue https://github.com/python-intelhex/intelhex/issues/4) -* The main activity of the IntelHex project slowly drifting towards - GitHub - the main social network for OSS developers. - I'd really like to get some help from additional maintainer though. -* API changes: ``IntelHex.dump()`` method gets new optional parameters: - ``width``, ``withpadding`` to control generation of output text. - (patch from GitHub user durexyl) -* Script ``hex2dump.py`` gets new option ``--width`` to support - corresponding parameter in ``IntelHex.dump()`` method. - -2.0 (2015-04-12) ----------------- -* The same codebase can be run on both Python 2 (2.4-2.7) - and Python 3 (3.2+). No need to use 2to3. -* ``compat.py``: provide more helper functions and aliases to reduce changes - required to convert python 2 compatible sources to python 3. - The code becomes quite ugly, but such compatibility has its price. -* Python 3 compatibility: tobinstr should return bytes not unicode string - (Bug #1212698). -* Python 2: better support for long int addresses (over 2GB) - (Bug #1408934) - -1.5 (2013-08-02) ----------------- -* API changes: Functions tobinarray/tobinstr/tobinfile: - pad parameter is deprecated and will be removed in - future releases. Use IntelHex.padding attribute instead, - and don't pass pad as None explicitly please. - If you need to use size parameter, then use syntax like that: - ``ih.tobinarray(start=xxx, size=yyy)`` -* API changes: Functions tobinarray/tobinstr/tobinfile: - default value of pad is None now (was ``0xFF``) - to allow using value of ``IntelHex.padding`` - if no explicit pad specified. -* Fixed bug: wrong ``getopt`` error handling in some scripts. - (Thanks to Andy Mozhevilov for bug report) -* PEP-8 style improvements. (Thanks to Stefan Schmitt) -* ``IntelHex16bit.tobinarray`` method returns array of unsigned short - (words) values. (Feature request from Stefan Schmitt) -* Improved Python 3 compatibility (don't use old file() function). - (Thanks to Luis Panadero Guardeño for bug report) - -1.4 (2012-04-25) ----------------- -* New feature: compare 2 hex files using hex dump - as string representation. Feature available as - worker function diff_dumps() and as command-line - utility hexdiff.py (#627924). -* Changes in the codebase suggested by 2to3 tool to provide - compatibility with Python3. Now sources can be successfully - converted to Python3 with 2to3 utility. - See Python 3 notes in README.txt and documentation. - (Thanks to Bernhard Leiner for his help) -* Fixed bug #988148: ``IntelHex16bit`` should copy all public attributes - from source IntelHex 8-bit object. (Thanks to Morgan McClure) - -1.3 (2010-11-24) ----------------- -* ``hex2dump``: show 0x7F character as dot for better compatibility - with GNU less utility. -* tobinarray, tobinfile, tobinstr: added size parameter. (Bug #408748) -* fixed error in ``hexmerge.py`` script. (#676023) - -1.2 (2009-08-04) ----------------- -* Fixed bug 372620: tobinarray on empty file should return pad bytes - when address range explicitly specified. -* Improved docstrings: explicitly say that ``end`` param of to-* methods - is always inclusive. (see bug #372625 for details). -* Improved documentation on ``ih.dump(tofile)``. - -1.1 (2009-03-12) ----------------- -* Fixed bug in writing hex files with small chains of bytes -* Improved Python 2.6 compatibility - -1.0 (2009-01-01) ----------------- -* Improved API, better performance -* New User Manual (Zachary Clifford) - -0.9 (2007-06-16) ----------------- -New API release. - -* New API -* Performance improvements: read hex file now ~45% faster - -0.8.6 (2007-04-27) ------------------- -Bug fixes and performance improvements. - -* ``IntelHex`` is able to read/write start address records - (HEX record type ``03`` and ``05``). (fix bug #109872) -* Backport (from 0.9 branch) of performance improvements - for reading hex files - -0.8.5 (2007-02-26) ------------------- -BugFix Release. - -Performance improvements for writing big hex files -when starting address is far from 0. Patch from Heiko Henkelmann. - -0.8.4 (2007-02-26) ------------------- -License added. - -The code is actually licensed under BSD, but there was -no LICENSE file in sources archive. Added license file -and explicit declaration in the source code. - -0.8.3 (2006-09-05) ------------------- -BugFix Release. - -Fix writing hex files with extended linear records -(when address overlaps 64K boundary). Patch from Henrik Maier. - -0.8.2 (2006-04-11) ------------------- -Major improvements release. - -* Introduced new class ``IntelHex16bit`` for manipulate data as 16-bit values -* You can manipulate data using dictionary-like interface - (i.e. syntax like: ``ih[addr] = value``) -* Added new method ``writefile(file)`` for writing data to hex file -* Using unittest for testing functionality - -0.6 (2006-03) -------------- -Convertor engine ``hex2bin`` extracted to stand-alone function -for using by external clients of intelhex. - -0.5 (2005) ----------- -First public release. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bae20d0 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# intelhex +Python IntelHex library + +Simple homepage for IntelHex project. diff --git a/README.rst b/README.rst deleted file mode 100644 index 00239ba..0000000 --- a/README.rst +++ /dev/null @@ -1,56 +0,0 @@ -Python IntelHex library -*********************** - -Introduction ------------- -The Intel HEX file format is widely used in microprocessors and microcontrollers -area (embedded systems etc) as the de facto standard -for representation of code to be programmed into microelectronic devices. - -This work implements an ``intelhex`` Python library to read, write, -create from scratch and manipulate data from Intel HEX file format. - -The distribution package also includes several convenience Python scripts, -including "classic" ``hex2bin`` and ``bin2hex`` converters and more, -those based on the library itself. Check the docs to know more. - -License -------- -The code is distributed under BSD license, -see `LICENSE.txt `_. - -In short: you can use IntelHex library in your project without *any* -restrictions. - -Supported Python versions -------------------------- -IntelHex library supports Python 3 (3.5 or later) only. The 2.2.1 release was -the last one which has been checked against Python 2.7 and Python 3 until 3.5. - -Install -------- -Install using ``pip`` (recommended, no separate download required):: - - pip install intelhex - -Download --------- -* https://pypi.org/project/IntelHex/ -* https://github.com/python-intelhex/intelhex/releases - -Source code, bug reports, patches ---------------------------------- -IntelHex on GitHub: - -https://github.com/python-intelhex/intelhex - -User manual ------------ -User manual for IntelHex is available in the sources ``docs/manual/`` directory. -You can browse User Manual online: - -https://readthedocs.org/projects/python-intelhex/ - -Changelog ---------- -See `NEWS.rst `_ diff --git a/docs/intelhex.pdf b/docs/intelhex.pdf deleted file mode 100644 index efa93af..0000000 Binary files a/docs/intelhex.pdf and /dev/null differ diff --git a/docs/manual.txt b/docs/manual.txt deleted file mode 100644 index 2935871..0000000 --- a/docs/manual.txt +++ /dev/null @@ -1,60 +0,0 @@ ------------------------------------ -Python IntelHex Library User Manual ------------------------------------ - -:Version: 2.3.0 - -.. contents:: -.. sectnum:: - -Introduction ------------- -.. include:: manual/part1-1.txt -.. include:: manual/part1-2.txt -.. include:: manual/part1-3.txt -.. include:: manual/part1-4.txt - -Basic API and usage -------------------- -.. include:: manual/part2-1.txt -.. include:: manual/part2-2.txt -.. include:: manual/part2-3.txt -.. include:: manual/part2-4.txt -.. include:: manual/part2-5.txt -.. include:: manual/part2-6.txt -.. include:: manual/part2-7.txt -.. include:: manual/part2-8.txt - -Convenience Scripts -------------------- -When IntelHex is installed and added to the system path, -some scripts are available for usage. -Each one is meant to be operated from the command line. -They provide help if called incorrectly. - -.. include:: manual/part3-1.txt -.. include:: manual/part3-2.txt -.. include:: manual/part3-3.txt -.. include:: manual/part3-4.txt -.. include:: manual/part3-5.txt -.. include:: manual/part3-6.txt - -Embedding into other projects -***************************** -IntelHex should be easy to embed in other projects. -The directory ``intelhex`` containing ``__init__.py`` can be directly placed -in a depending project and used directly. From that project the same import -statements described above can be used to make the library work. -From other projects the import statement would change to:: - - >>> from myproject.intelhex import IntelHex - -Alternatively, the IntelHex package can be installed into the site-packages -directory and used as a system package. - -In either case, IntelHex is distributed with a BSD-style license. -This permits you to use it in any way you see fit, provided that the package -is appropriately credited. - - -.. include:: manual/appendix-a.txt diff --git a/docs/manual/Makefile b/docs/manual/Makefile deleted file mode 100644 index 4a80277..0000000 --- a/docs/manual/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html web pickle htmlhelp latex changes linkcheck - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview over all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - -clean: - -rm -rf .build/* - -html: -# mkdir -p .build/html .build/doctrees - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html - @echo - @echo "Build finished. The HTML pages are in .build/html." - -pickle: - mkdir -p .build/pickle .build/doctrees - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -web: pickle - -json: - mkdir -p .build/json .build/doctrees - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) .build/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - mkdir -p .build/htmlhelp .build/doctrees - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in .build/htmlhelp." - -latex: - mkdir -p .build/latex .build/doctrees - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex - @echo - @echo "Build finished; the LaTeX files are in .build/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - mkdir -p .build/changes .build/doctrees - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes - @echo - @echo "The overview file is in .build/changes." - -linkcheck: - mkdir -p .build/linkcheck .build/doctrees - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in .build/linkcheck/output.txt." diff --git a/docs/manual/appendix-a.txt b/docs/manual/appendix-a.txt deleted file mode 100644 index e627d18..0000000 --- a/docs/manual/appendix-a.txt +++ /dev/null @@ -1,29 +0,0 @@ -Appendix A. IntelHex Errors Hierarchy -------------------------------------- - -* ``IntelHexError`` - base error - - * ``HexReaderError`` - general hex reader error - - * ``AddressOverlapError`` - data for the same address overlap - * ``HexRecordError`` - hex record decoder base error - - * ``RecordLengthError`` - record has invalid length - * ``RecordTypeError`` - record has invalid type (RECTYP) - * ``RecordChecksumError`` - record checksum mismatch - * ``EOFRecordError`` - invalid EOF record (type 01) - * ``ExtendedAddressRecordError`` - extended address record base error - - * ``ExtendedSegmentAddressRecordError`` - invalid extended segment address record (type 02) - * ``ExtendedLinearAddressRecordError`` - invalid extended linear address record (type 04) - - * ``StartAddressRecordError`` - start address record base error - - * ``StartSegmentAddressRecordError`` - invalid start segment address record (type 03) - * ``StartLinearAddressRecordError`` - invalid start linear address record (type 05) - * ``DuplicateStartAddressRecordError`` - start address record appears twice - * ``InvalidStartAddressValueError`` - invalid value of start addr record - - * ``BadAccess16bit`` - not enough data to read 16 bit value - * ``NotEnoughDataError`` - not enough data to read N contiguous bytes - * ``EmptyIntelHexError`` - requested operation cannot be performed with empty object diff --git a/docs/manual/conf.py b/docs/manual/conf.py deleted file mode 100644 index cf39f06..0000000 --- a/docs/manual/conf.py +++ /dev/null @@ -1,197 +0,0 @@ -# -*- coding: utf-8 -*- -# -# IntelHex documentation build configuration file, created by -# sphinx-quickstart on Thu Jan 01 06:25:34 2009. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# The contents of this file are pickled, so don't put values in the namespace -# that aren't pickleable (module imports are okay, they're removed automatically). -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If your extensions are in another directory, add it here. If the directory -# is relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -#sys.path.append(os.path.abspath('.')) - -# General configuration -# --------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['.templates'] - -# The suffix of source filenames. -source_suffix = '.txt' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'Python IntelHex library' -copyright = '2005-2018, Alexander Belchenko' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. - -# let's use it right from the intelhex package -exec(open('../../intelhex/__version__.py').read()) -VERSION = version_str # from __version__.py - -# -# The short X.Y version. -version = VERSION -# The full version, including alpha/beta/rc tags. -release = VERSION - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['.build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - - -# Options for HTML output -# ----------------------- - -#html_theme = 'classic' - -# The style sheet to use for HTML and HTML Help pages. A file of that name -# must exist either in Sphinx' static/ path, or in one of the custom paths -# given in html_static_path. -#html_style = 'default.css' - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['.static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, the reST sources are included in the HTML build as _sources/. -#html_copy_source = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'PythonIntelhexLibrary' - - -# Options for LaTeX output -# ------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, document class [howto/manual]). -latex_documents = [ - ('index', 'IntelHex.tex', 'Python IntelHex library Documentation', - 'Alexander Belchenko', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True diff --git a/docs/manual/index.txt b/docs/manual/index.txt deleted file mode 100644 index a14609a..0000000 --- a/docs/manual/index.txt +++ /dev/null @@ -1,24 +0,0 @@ -.. IntelHex documentation master file, created by sphinx-quickstart on Thu Jan 01 06:25:34 2009. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Python IntelHex Library User Manual ------------------------------------ - -Contents: - -.. toctree:: - :maxdepth: 3 - - part1 - part2 - part3 - part4 - appendix-a - -Indices and tables ------------------- - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/manual/part1-1.txt b/docs/manual/part1-1.txt deleted file mode 100644 index 673fb69..0000000 --- a/docs/manual/part1-1.txt +++ /dev/null @@ -1,53 +0,0 @@ -About -***** -The Intel HEX file format is widely used in microprocessors and microcontrollers -area as the de facto standard for code representation for microelectronic devices programming. - -This work implements an **intelhex** Python library to read, write, -create from scratch and manipulate data from HEX (also known as Intel HEX) -file format. These operations are provided by ``IntelHex`` class. - -The distribution package also includes several convenience Python scripts -to do basic tasks that utilize this library. The ``bin2hex.py`` script -converts binary data to HEX, and the ``hex2bin.py`` works the other direction. -``hex2dump.py`` converts data from HEX to a hexdump which is useful for -inspecting data, and ``hexmerge.py`` merges multiple HEX files into one. -In addition you can try inspecting differences between two HEX files with -``hexdiff.py`` utility which uses dump output similar to ``hex2dump.py``. - -You can find IntelHex library on PyPI: - -https://pypi.python.org/pypi/IntelHex - -on GitHub: - -https://github.com/python-intelhex/intelhex - - -Motivation -~~~~~~~~~~ -This work was partially inspired by SRecord_ software at the moment -when I stuck with its limitations and unintuitive behavior (for me personally). - -So I've made this library and related tools which give me -full control over data and HEX file creation. -Not the best reason to start yet another project. -But, as you probably know, nothing is better than scratch our own itches, -especially if you want to re-implement something -in your favorite programming language. - -Over the years it turned out that my small python library was very useful -to many people, and allowed them not only to create utilities to manipulate -with HEX files, but also to create custom bootloaders for their devices. - -I started writing this library in 2005, and now more than 10 years later -it's still alive and useful to other developers. -That keeps me working on improving the code, -even though I don't work on embedding systems for some time. - -If you find IntelHex library useful, please send me email -and tell a bit about how you're using it and in which projects/areas. -That will not only satisfy my curiosity but also will help me to keep working -on this project. - -.. _SRecord: http://srecord.sourceforge.net/ diff --git a/docs/manual/part1-2.txt b/docs/manual/part1-2.txt deleted file mode 100644 index 2906035..0000000 --- a/docs/manual/part1-2.txt +++ /dev/null @@ -1,4 +0,0 @@ -License -******* -The code distributed under the BSD license. -See LICENSE.txt in sources archive. diff --git a/docs/manual/part1-3.txt b/docs/manual/part1-3.txt deleted file mode 100644 index 6a9796c..0000000 --- a/docs/manual/part1-3.txt +++ /dev/null @@ -1,90 +0,0 @@ -Installation -************ - -Note: some commands below have `sudo` as first word. -It's required only on Linux or Mac OS X. -Omit the prefix if you're on Windows. - -Installing with pip -~~~~~~~~~~~~~~~~~~~ -If you just need IntelHex library installed as your system python library -then it's better to use modern tool called ``pip`` -(http://www.pip-installer.org/en/latest/) -to install with the command: - - sudo pip install intelhex - -The latest versions of Python interpreter (like 2.7.9, or 3.4.x and later) -have pip in the standard installer/distribution. - -The simplest way to check whether you have pip installed -is to check command (for Python 2.5+): - - python -m pip list - -If this does not work, you can install pip by downloading single file -from this page: https://pip.pypa.io/en/latest/installing.html#install-pip -and run it as - - sudo python get-pip.py - - -Download sources -~~~~~~~~~~~~~~~~ -You can get archive with the latest released code, docs and other files -from PyPI: - -https://pypi.python.org/pypi/IntelHex - -You can get the archive with the released code from corresponding section -of GitHub project: - -https://github.com/python-intelhex/intelhex/releases - -or even unreleased bleeding edge code from GitHub page: - -https://github.com/python-intelhex/intelhex - -Use the corresponding menu item in the right-hand side bar on that page -(e.g. "Download ZIP"). - - -Get source code with git -~~~~~~~~~~~~~~~~~~~~~~~~ - git clone https://github.com/python-intelhex/intelhex.git - - -Install from sources -~~~~~~~~~~~~~~~~~~~~ -IntelHex has got stadard setup.py installation script. -Assuming Python is properly installed on your platform, -installation should require just running of the following command -from the root directory of the sources:: - - sudo python setup.py install - -This will install the intelhex package into your system's site-packages -directory and place the helper scripts in your Python site-packages -binaries directory. Once it is done, any other Python scripts or modules -should be able to import the package using:: - - >>> from intelhex import IntelHex - -The scripts should be in your PATH so that they could be called from anywhere -in the file system. - -See the Python distutils website for more information, or try typing, -``python setup.py --help`` from the root directory of the sources. - -Note for Windows users -~~~~~~~~~~~~~~~~~~~~~~ -Please note that for historical reasons IntelHex library doesn't use -setuptools for installation task, therefore we don't create exe-wrappers -for helper scripts as hex2bin.py, bin2hex.py and other mentioned in this -documentation (see section Convenience Scripts). - -You can find these scripts in your python Script directory -(usually `C:\\PythonXY\\Scripts`). -You need either to create batch file to run them, or use Python interpreter: - - python C:\\PythonXY\\Scripts\\hex2bin.py ... diff --git a/docs/manual/part1-4.txt b/docs/manual/part1-4.txt deleted file mode 100644 index cfd3a2a..0000000 --- a/docs/manual/part1-4.txt +++ /dev/null @@ -1,26 +0,0 @@ -Python 3 compatibility -********************** -Intelhex library supports Python 2 (2.4-2.7) and Python 3 (3.2-3.6) without -external libraries or 2to3 tool. Enjoy. - -I've successfully run unit tests of IntelHex against following versions of -Python: - - 2.4.4, 2.5.4, 2.6.6 (32/64 bits), 2.7.9 (32/64 bits), - 3.2.5 (32/64 bits), 3.3.5 (32/64 bits), 3.4.3 (32/64 bits), - 3.5.0a3 (32/64 bits), - and also PyPy 2.5.1 (which is Python 2.7.9) - - -Which Python version should you use? ------------------------------------- -If you don't really know which version of Python (2 or 3) you should use with -IntelHex then please check following pre-requisites: - -1) Are you already have some Python installed on your computer and that - version is supported by IntelHex (see above)? -2) Should you use another third-party libraries? If so, check their - requirements. -3) Python 2.7 is the safest choice so far, but if you have a chance - then try latest stable Python 3 version. -4) Updated by January 2018 - Python 3 is highly recommended. diff --git a/docs/manual/part1.txt b/docs/manual/part1.txt deleted file mode 100644 index c572859..0000000 --- a/docs/manual/part1.txt +++ /dev/null @@ -1,7 +0,0 @@ -Introduction ------------- - -.. toctree:: - :glob: - - part1-* diff --git a/docs/manual/part2-1.txt b/docs/manual/part2-1.txt deleted file mode 100644 index e03dea2..0000000 --- a/docs/manual/part2-1.txt +++ /dev/null @@ -1,18 +0,0 @@ -Initializing the class -********************** -Example of typical initialization of ``IntelHex`` class:: - ->>> from intelhex import IntelHex ->>> ih = IntelHex("foo.hex") - -In the second line we are creating an instance of the class. -The constructor optionally takes data to initialize the class. -This can be the name of the HEX file, a file-like object, a dictionary, -or another instance of IntelHex. If specified, this source is automatically -read and decoded. Because of the flexibility of file-like objects in Python, -objects like sys.stdin can be used. - -If the source is another instance of IntelHex, the new object will become -a copy of the source. Finally, a Python dictionary may be specified. -This dictionary should have keys equal to memory locations and values equal -to the data stored in those locations. See the docstrings for more details. diff --git a/docs/manual/part2-2.txt b/docs/manual/part2-2.txt deleted file mode 100644 index 841adea..0000000 --- a/docs/manual/part2-2.txt +++ /dev/null @@ -1,43 +0,0 @@ -Reading data -************ -Once created, an IntelHex object can be loaded with data. -This is only necessary if "source" was unspecified in the constructor. -You can also load data several times (but if addresses in those files overlap -you get exception ``AddressOverlapError``). This error is only raised when -reading from hex files. When reading from other formats, without explicitly -calling ``merge``, the data will be overwritten. E.g.:: - - >>> from intelhex import IntelHex - >>> ih = IntelHex() # create empty object - >>> ih.loadhex('foo.hex') # load from hex - >>> ih.loadfile('bar.hex',format='hex') # also load from hex - >>> ih.fromfile('bar.hex',format='hex') # also load from hex - -**NOTE**: using ``IntelHex.fromfile`` is recommended way. - -All of the above examples will read from HEX files. -IntelHex also supports reading straight binary files. For example:: - - >>> from intelhex import IntelHex - >>> ih = IntelHex() # create empty object - >>> ih.loadbin('foo.bin') # load from bin - >>> ih.fromfile('bar.bin',format='bin') # also load from bin - >>> ih.loadbin('baz.bin',offset=0x1000) # load binary data and place them - >>> # starting with specified offset - -Finally, data can be loaded from an appropriate Python dictionary. -This will permit you to store the data in an IntelHex object -to a builtin dictionary and restore the object at a later time. -For example:: - - >>> from intelhex import IntelHex - >>> ih = IntelHex('foo.hex') # create empty object - >>> pydict = ih.todict() # dump contents to pydict - -...do something with the dictionary... - -:: - - >>> newIH = IntelHex(pydict) # recreate object with dict - >>> another = IntelHex() # make a blank instance - >>> another.fromdict(pydict) # now another is the same as newIH diff --git a/docs/manual/part2-3.txt b/docs/manual/part2-3.txt deleted file mode 100644 index d68a378..0000000 --- a/docs/manual/part2-3.txt +++ /dev/null @@ -1,30 +0,0 @@ -Basic data inspection -********************* -You can get or modify some data by address in the usual way: -via Python indexing operations:: - - >>> print ih[0] # read data from address 0 - -When you need to work with 16-bit data stored in 8-bit Intel HEX files -you need to use class ``IntelHex16bit``. This class is derived from IntelHex -and has all its methods. Some of methods have been modified to implement -16-bit behaviour. - -**NOTE:** ``IntelHex16bit`` class despite its name **can't handle** real HEX16 -files. Initially ``IntelHex16bit`` has been created as helper class to work with -HEX files for Microchip's PIC16 family firmware. It may or may not work for -your purpose. - -This class assumes the data is in Little Endian byte order. -The data can be accessed exactly like above, except that data returned will be -16 bits, and the addresses should be word addresses. - -Another useful inspection tool is the dump command. This will output -the entire contents of the hex file to stdout or to a specified file object -like so:: - - >>> ih.dump() # dump contents of ih to stdout in tabular hexdump format - - >>> f = open('hexdump.txt', 'w') # open file for writing - >>> ih.dump(f) # dump to file object - >>> f.close() # close file diff --git a/docs/manual/part2-4.txt b/docs/manual/part2-4.txt deleted file mode 100644 index df1e306..0000000 --- a/docs/manual/part2-4.txt +++ /dev/null @@ -1,88 +0,0 @@ -More data inspection -******************** -IntelHex provides some metadata about the hex file it contains. -To obtain address limits use methods ``.minaddr()`` and ``.maxaddr()``. -These are computed based on the lowest and highest used memory spaces -respectively. - -Some linkers write to produced HEX file information about start address -(either record 03 or 05). IntelHex is able correctly read such records -and store information internally in ``start_addr`` attribute that itself -is either ``None`` or a dictionary with the address value(s). - -When input HEX file contains record type 03 (Start Segment Address Record), -``start_addr`` takes value:: - - {'CS': XXX, 'IP': YYY} - -Here: - -* ``XXX`` is value of CS register -* ``YYY`` is value of IP register - -To obtain or change ``CS`` or ``IP`` value you need to use their names as keys -for ``start_addr`` dictionary:: - - >>> ih = IntelHex('file_with_03.hex') - >>> print ih.start_addr['CS'] - >>> print ih.start_addr['IP'] - -When input HEX file contains record type 05 (Start Linear Address Record), -``start_addr`` takes value:: - - {'EIP': ZZZ} - -Here ``ZZZ`` is value of EIP register. - -Example:: - - >>> ih = IntelHex('file_with_05.hex') - >>> print ih.start_addr['EIP'] - -You can manually set required start address:: - - >>> ih.start_addr = {'CS': 0x1234, 'IP': 0x5678} - >>> ih.start_addr = {'EIP': 0x12345678} - -To delete start address info give value ``None`` or empty dictionary:: - - >>> ih.start_addr = None - >>> ih.start_addr = {} - -When you write data to HEX file you can disable writing start address -with additional argument ``write_start_addr``:: - - >>> ih.write_hex_file('out.hex') # by default writing start address - >>> ih.write_hex_file('out.hex', True) # as above - >>> ih.write_hex_file('out.hex', False) # don't write start address - -When ``start_addr`` is ``None`` or an empty dictionary nothing will be written -regardless of ``write_start_addr`` argument value. - -For more information about start address, please see the Intel Hex file format -specification. - -Because Intel Hex files do not specify every location in memory, -it is necessary to have a padding byte defined. Whenever a read is attempted -from an address that is unspecified, the padding byte is returned. -This default data is set via attribute ``.padding`` of class instance. -This defaults to '0xFF', but it can be changed by the user like so:: - - >>> print ih[0] # prints 0xFF because this location is blank - >>> ih.padding = 0x00 # change padding byte - >>> print ih[0] # prints 0x00 because this location is blank - -Summarizing the data chunks -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One of the more useful properties of HEX files is that they can specify data -in discontinuous segments. There are two main methods to summarize which -data addresses are occupied:: - - >>> ih.addresses() - >>> ih.segments() - -The first will return a list of occupied data addresses in sorted order. The -second will return a list of 2-tuples objects, in sorted order, representing -start and stop addresses of contiguous segment chunks of occupied data. -Those 2-tuples are suitable to be used as ``start`` and ``stop`` -arguments of standard ``range`` function. diff --git a/docs/manual/part2-5.txt b/docs/manual/part2-5.txt deleted file mode 100644 index 6b5dd7d..0000000 --- a/docs/manual/part2-5.txt +++ /dev/null @@ -1,72 +0,0 @@ -Writing out data -**************** -Data contained in IntelHex can be written out in a few different formats, -including HEX, bin, or python dictionaries. - -You can write out HEX data contained in object by method ``.write_hex_file(f)``. -Parameter ``f`` should be filename or file-like object. -Note that this can include builtins like sys.stdout. -Also you can use the universal tofile. - -To convert data of IntelHex object to HEX8 file format without actually saving it -to disk you can use the builtin StringIO file-like object, e.g.:: - - >>> from cStringIO import StringIO - >>> from intelhex import IntelHex - >>> ih = IntelHex() - >>> ih[0] = 0x55 - >>> sio = StringIO() - >>> ih.write_hex_file(sio) - >>> hexstr = sio.getvalue() - >>> sio.close() - -Variable ``hexstr`` will contain a string with the content of a HEX8 file. - -You can customize hex file output with following optional arguments -to ``write_hex_file`` call: - - * ``write_start_addr`` - you can disable start address record in new hex file; - * ``eolstyle`` - you can force ``CRLF`` line endings in new hex file. - * ``byte_count`` - you can control how many bytes should be written to each - data record. - - -Data converters -~~~~~~~~~~~~~~~ - -To write data as a hex file with default settings you also can use -universal method ``tofile``:: - - # the code below is the same as "ih.write_hex_file(sio)" - >>> ih.tofile(sio, format='hex') - -Class IntelHex has several methods for converting data of IntelHex objects -into binary form: - -* ``tobinarray`` (returns array of unsigned char bytes); -* ``tobinstr`` (returns string of bytes); -* ``tobinfile`` (convert content to binary form and write to file). - -Example:: - - >>> from intelhex import IntelHex - >>> ih = IntelHex("foo.hex") - >>> ih.tobinfile("foo.bin") - -Also you can use universal method ``tofile`` to write data as binary file:: - - >>> ih.tofile("foo.bin", format='bin') - - -Writing data in chunks -~~~~~~~~~~~~~~~~~~~~~~ -If you need to get binary data from IntelHex as series of chunks then you can -pass to ``tobinarray``/``tobinstr`` methods either start/end addresses -or start address and required size of the chunk. This could be useful if -you're creating Eeprom/Flash IC programmer or bootloader. -:: - - EEPROM_SIZE = 8192 # 8K bytes - BLOCK_SIZE = 128 # 128 bytes - for addr in range(0, EEPROM_SIZE, BLOCK_SIZE): - eeprom.i2c_write(addr, ih.tobinarray(start=addr, size=BLOCK_SIZE)) diff --git a/docs/manual/part2-6.txt b/docs/manual/part2-6.txt deleted file mode 100644 index 7a44943..0000000 --- a/docs/manual/part2-6.txt +++ /dev/null @@ -1,24 +0,0 @@ -Merging two hex files -********************* -IntelHex supports merging two different hex files into one. -This is done by initializing one IntelHex object with data -and calling its merge method:: - - >>> original = IntelHex("foo.hex") - >>> new = IntelHex("bar.hex") - >>> original.merge(new, overlap='replace') - -Now original will contain foo.hex merged with bar.hex. -The overlap parameter specifies what should be done when memory -locations in the original object overlap with locations in the new object. -It can take three options: - -* ``error`` - stop and raise an exception (default) -* ``ignore`` - keep data from the original that contains data at overlapped address -* ``replace`` - use data from the new object that contains data at overlapped address - -You can merge only part of other hex file by using slice index notation:: - - >>> original = IntelHex("foo.hex") - >>> new = IntelHex("bar.hex") - >>> original.merge(new[0x0F:0x3F]) diff --git a/docs/manual/part2-7.txt b/docs/manual/part2-7.txt deleted file mode 100644 index 354d485..0000000 --- a/docs/manual/part2-7.txt +++ /dev/null @@ -1,46 +0,0 @@ -Creating Intel Hex files from scratch -************************************* -Some facilities are provided for synthesizing Intel Hex files from scratch. -These can also be used to modify a hex file in place. -Just as you can use indexed reads to retrieve data, you can use indexed writes -to modify the file, e.g.:: - - >>> ih[1] = 0x55 # modify data at address 1 - -A common usage would be to read a hex file with IntelHex, use the above syntax -to modify it, and then write out the modified file. The above command can be used -on an empty IntelHex object to synthesize a hex file from scratch. - -Another important feature helps work with C strings via ``putsz``/``getsz``, e.g.:: - - >>> ih.putsz(0x100,"A string") - -This places "A string" followed by a terminating NULL character in address 0x100. -The ``getsz`` method similarly retrieves a null terminated string from a specified address like so:: - - >>> ih.getsz(0x100) - -This should retrieve the "A string" we stored earlier. - -Additionally, ``puts``/``gets`` can be used to retrieve strings of specific length -from the hex file like so:: - - >>> ih.puts(0x100,"data") - >>> ih.gets(0x100,4) - -The second command should retrieve the characters 'd','a','t','a'. -These methods do not use terminating NULLs, so the data need not be interpreted as a string. -One usage of these commands comes from the Python ``struct`` module. -This module allows the programmer to specify a C struct, and it will allow conversion -between the variables and a packed string representation for use with -``puts``/``gets``. -For example, suppose we need to deal with a struct containing a char, a short, and a float:: - - >>> import struct - >>> formatstring = 'chf' # see Python docs for full list of valid struct formats - >>> ih.puts(0x10, struct.pack(formatstring,'a',24,18.6)) # put data in hex file - >>> (mychar,myshort,myfloat) = struct.unpack(formatstring, ih.gets(0x10,7) - -Now ``mychar``, ``myshort``, and ``myfloat`` should contain the original data -(assuming ``sizeof(float) = 4`` on this platform, otherwise the size may be -wrong). diff --git a/docs/manual/part2-8.txt b/docs/manual/part2-8.txt deleted file mode 100644 index 0ec3e4a..0000000 --- a/docs/manual/part2-8.txt +++ /dev/null @@ -1,17 +0,0 @@ -Handling errors -*************** -Many of the methods in IntelHex throw Python exceptions during error conditions. -These can be caught and handled using try...except blocks like so:: - - >>> try: - ... mystring = ih.gets(0x20,20) - >>> except intelhex.NotEnoughDataError: - ... print "There is not enough data at that location" - -See the API docs for information about errors raised by IntelHex. -They are all subclasses of IntelHexError, so the except block above could be used -to catch all of them. If your application has a way to gracefully handle these -exceptions, they should be caught. Otherwise, Python will exit with a descriptive -error message about the uncaught exception. - -See `Appendix A `_ for error classes hierarchy. diff --git a/docs/manual/part2.txt b/docs/manual/part2.txt deleted file mode 100644 index bb5b8d6..0000000 --- a/docs/manual/part2.txt +++ /dev/null @@ -1,7 +0,0 @@ -Basic API and usage -------------------- - -.. toctree:: - :glob: - - part2-* diff --git a/docs/manual/part3-1.txt b/docs/manual/part3-1.txt deleted file mode 100644 index 8b29f9d..0000000 --- a/docs/manual/part3-1.txt +++ /dev/null @@ -1,31 +0,0 @@ -Script ``hex2bin.py`` -********************* -You can use ``hex2bin.py`` as handy hex-to-bin converter. -This script is just a frontend for function ``hex2bin`` from intelhex package. -:: - - Usage: - python hex2bin.py [options] INFILE [OUTFILE] - - Arguments: - INFILE name of hex file for processing. - OUTFILE name of output file. If omitted then output - will be writing to stdout. - - - Options: - -h, --help this help message. - -p, --pad=FF pad byte for empty spaces (hex value). - -r, --range=START:END specify address range for writing output - (hex value). - Range can be in form 'START:' or ':END'. - -l, --length=NNNN, - -s, --size=NNNN size of output (decimal value). - -Per example, converting content of foo.hex to foo.bin addresses from 0 to FF:: - - $ python hex2bin.py -r 0000:00FF foo.hex - -Or (equivalent):: - - $ python hex2bin.py -r 0000: -s 256 foo.hex diff --git a/docs/manual/part3-2.txt b/docs/manual/part3-2.txt deleted file mode 100644 index cd67855..0000000 --- a/docs/manual/part3-2.txt +++ /dev/null @@ -1,19 +0,0 @@ -Script ``bin2hex.py`` -********************************* -You can use bin2hex.py as simple bin-to-hex convertor. This script is -just a frontend for function ``bin2hex`` from intelhex package. -:: - - Usage: - python bin2hex.py [options] INFILE [OUTFILE] - - Arguments: - INFILE name of bin file for processing. - Use '-' for reading from stdin. - - OUTFILE name of output file. If omitted then output - will be writing to stdout. - - Options: - -h, --help this help message. - --offset=N offset for loading bin file (default: 0). diff --git a/docs/manual/part3-3.txt b/docs/manual/part3-3.txt deleted file mode 100644 index 0f59aa8..0000000 --- a/docs/manual/part3-3.txt +++ /dev/null @@ -1,18 +0,0 @@ -Script ``hex2dump.py`` -*********************** -This is a script to dump a hex file to a hexdump format. It is a frontend for -``dump`` function in ``IntelHex`` class. -:: - - Usage: - python hex2dump.py [options] HEXFILE - - Options: - -h, --help this help message. - -r, --range=START:END specify address range for dumping - (ascii hex value). - Range can be in form 'START:' or ':END'. - - Arguments: - HEXFILE name of hex file for processing (use '-' to read - from stdin) diff --git a/docs/manual/part3-4.txt b/docs/manual/part3-4.txt deleted file mode 100644 index 7b5b8b8..0000000 --- a/docs/manual/part3-4.txt +++ /dev/null @@ -1,45 +0,0 @@ -Script ``hexmerge.py`` -********************************** -This is a script to merge two different hex files. It is a frontend for the -``merge`` function in ``IntelHex`` class. -:: - - Usage: - python hexmerge.py [options] FILES... - - Options: - -h, --help this help message. - -o, --output=FILENAME output file name (emit output to stdout - if option is not specified) - -r, --range=START:END specify address range for output - (ascii hex value). - Range can be in form 'START:' or ':END'. - --no-start-addr Don't write start addr to output file. - --overlap=METHOD What to do when data in files overlapped. - Supported variants: - * error -- stop and show error message (default) - * ignore -- keep data from first file that - contains data at overlapped address - * replace -- use data from last file that - contains data at overlapped address - - Arguments: - FILES list of hex files for merging - (use '-' to read content from stdin) - - You can specify address range for each file in the form: - - filename:START:END - - See description of range option above. - - You can omit START or END, so supported variants are: - - filename:START: read filename and use data starting from START addr - filename::END read filename and use data till END addr - - Use entire file content: - - filename - or - filename:: diff --git a/docs/manual/part3-5.txt b/docs/manual/part3-5.txt deleted file mode 100644 index 13ab55a..0000000 --- a/docs/manual/part3-5.txt +++ /dev/null @@ -1,19 +0,0 @@ -Script ``hexdiff.py`` -********************* -This is a script to diff context of two hex files. - -To create human-readable diff this utility converts -both hex files to hex dumps first, -and then utility compares those hex dumps and -produces unified diff output for changes. - -:: - - hexdiff: diff dumps of 2 hex files. - - Usage: - python hexdiff.py [options] FILE1 FILE2 - - Options: - -h, --help this help message. - -v, --version version info. diff --git a/docs/manual/part3-6.txt b/docs/manual/part3-6.txt deleted file mode 100644 index 871805e..0000000 --- a/docs/manual/part3-6.txt +++ /dev/null @@ -1,19 +0,0 @@ -Script ``hexinfo.py`` -********************* -This is a script to summarize a hex file's contents. - -This utility creates a YAML-formatted, human-readable -summary of a set of HEX files. It includes the file name, -execution start address (if any), and the address ranges -covered by the data (if any). - -:: - - hexinfo: summarize a hex file's contents. - - Usage: - python hexinfo.py [options] FILE [ FILE ... ] - - Options: - -h, --help this help message. - -v, --version version info. diff --git a/docs/manual/part3.txt b/docs/manual/part3.txt deleted file mode 100644 index 5049394..0000000 --- a/docs/manual/part3.txt +++ /dev/null @@ -1,12 +0,0 @@ -Convenience Scripts -------------------- - -When IntelHex is installed and added to the system path, -some scripts are available for usage. -Each one is meant to be operated from the command line. -They provide help if called incorrectly. - -.. toctree:: - :glob: - - part3-* diff --git a/docs/manual/part4.txt b/docs/manual/part4.txt deleted file mode 100644 index 4d0c0a9..0000000 --- a/docs/manual/part4.txt +++ /dev/null @@ -1,22 +0,0 @@ -Embedding into other projects -***************************** -IntelHex should be easy to embed in other projects. -The directory ``intelhex`` containing ``__init__.py`` can be directly placed -in a depending project and used directly. From that project the same import -statements described above can be used to make the library work. -From other projects the import statement would change to:: - - >>> from myproject.intelhex import IntelHex - -Alternatively, the IntelHex package can be installed into the site-packages -directory and used as a system package. - -In either case, IntelHex is distributed with a BSD-style license. -This permits you to use it in any way you see fit, provided that the package -is appropriately credited. - -If you're using IntelHex library in your open-source project, or your company -created freely available set of tools, utilities or sdk based on IntelHex -library - please, send me email (to alexander belchenko at gmail com) -and tell something about your project. -I'd like to add name of your project/company to page "Who Uses IntelHex". diff --git a/images/bg_hr.png b/images/bg_hr.png new file mode 100644 index 0000000..514aee5 Binary files /dev/null and b/images/bg_hr.png differ diff --git a/images/blacktocat.png b/images/blacktocat.png new file mode 100644 index 0000000..e160053 Binary files /dev/null and b/images/blacktocat.png differ diff --git a/images/icon_download.png b/images/icon_download.png new file mode 100644 index 0000000..5a793f1 Binary files /dev/null and b/images/icon_download.png differ diff --git a/images/sprite_download.png b/images/sprite_download.png new file mode 100644 index 0000000..f9f8de2 Binary files /dev/null and b/images/sprite_download.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..6fc4220 --- /dev/null +++ b/index.html @@ -0,0 +1,79 @@ + + + + + + + + + + + Python IntelHex library + + + + + +
+
+ View on GitHub + +

Python IntelHex library

+

IntelHex files manipulating

+ +
+ Download this project as a .zip file + Download this project as a tar.gz file +
+
+
+ + +
+
+

+Welcome to GitHub Pages.

+ +

This automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:

+ +
$ cd your_repo_root/repo_name
+$ git fetch origin
+$ git checkout gh-pages
+
+ +

If you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.

+ +

+Designer Templates

+ +

We've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.

+ +

+Rather Drive Stick?

+ +

If you prefer to not use the automatic generator, push a branch named gh-pages to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.

+ +

+Authors and Contributors

+ +

You can @mention a GitHub username to generate a link to their profile. The resulting <a> element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.

+ +

+Support or Contact

+ +

Having trouble with Pages? Check out the documentation at https://help.github.com/pages or contact support@github.com and we’ll help you sort it out.

+
+
+ + + + + + + + diff --git a/intelhex/__init__.py b/intelhex/__init__.py deleted file mode 100644 index 155f17f..0000000 --- a/intelhex/__init__.py +++ /dev/null @@ -1,1384 +0,0 @@ -# Copyright (c) 2005-2018, Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -'''Intel HEX format manipulation library.''' - -__docformat__ = "javadoc" - -from array import array -from binascii import hexlify, unhexlify -from bisect import bisect_right -import os -import sys - -from intelhex.compat import ( - IntTypes, - StrType, - StringIO, - array_tobytes, - asbytes, - asstr, - dict_items_g, - dict_keys, - dict_keys_g, - range_g, - range_l, - ) - -from intelhex.getsizeof import total_size - - -class _DeprecatedParam(object): - pass - -_DEPRECATED = _DeprecatedParam() - - -class IntelHex(object): - ''' Intel HEX file reader. ''' - - def __init__(self, source=None): - ''' Constructor. If source specified, object will be initialized - with the contents of source. Otherwise the object will be empty. - - @param source source for initialization - (file name of HEX file, file object, addr dict or - other IntelHex object) - ''' - # public members - self.padding = 0x0FF - # Start Address - self.start_addr = None - - # private members - self._buf = {} - self._offset = 0 - - if source is not None: - if isinstance(source, StrType) or getattr(source, "read", None): - # load hex file - self.loadhex(source) - elif isinstance(source, dict): - self.fromdict(source) - elif isinstance(source, IntelHex): - self.padding = source.padding - if source.start_addr: - self.start_addr = source.start_addr.copy() - self._buf = source._buf.copy() - else: - raise ValueError("source: bad initializer type") - - def _decode_record(self, s, line=0): - '''Decode one record of HEX file. - - @param s line with HEX record. - @param line line number (for error messages). - - @raise EndOfFile if EOF record encountered. - ''' - s = s.rstrip('\r\n') - if not s: - return # empty line - - if s[0] == ':': - try: - bin = array('B', unhexlify(asbytes(s[1:]))) - except (TypeError, ValueError): - # this might be raised by unhexlify when odd hexascii digits - raise HexRecordError(line=line) - length = len(bin) - if length < 5: - raise HexRecordError(line=line) - else: - raise HexRecordError(line=line) - - record_length = bin[0] - if length != (5 + record_length): - raise RecordLengthError(line=line) - - addr = bin[1]*256 + bin[2] - - record_type = bin[3] - if not (0 <= record_type <= 5): - raise RecordTypeError(line=line) - - crc = sum(bin) - crc &= 0x0FF - if crc != 0: - raise RecordChecksumError(line=line) - - if record_type == 0: - # data record - addr += self._offset - for i in range_g(4, 4+record_length): - if not self._buf.get(addr, None) is None: - raise AddressOverlapError(address=addr, line=line) - self._buf[addr] = bin[i] - addr += 1 # FIXME: addr should be wrapped - # BUT after 02 record (at 64K boundary) - # and after 04 record (at 4G boundary) - - elif record_type == 1: - # end of file record - if record_length != 0: - raise EOFRecordError(line=line) - raise _EndOfFile - - elif record_type == 2: - # Extended 8086 Segment Record - if record_length != 2 or addr != 0: - raise ExtendedSegmentAddressRecordError(line=line) - self._offset = (bin[4]*256 + bin[5]) * 16 - - elif record_type == 4: - # Extended Linear Address Record - if record_length != 2 or addr != 0: - raise ExtendedLinearAddressRecordError(line=line) - self._offset = (bin[4]*256 + bin[5]) * 65536 - - elif record_type == 3: - # Start Segment Address Record - if record_length != 4 or addr != 0: - raise StartSegmentAddressRecordError(line=line) - if self.start_addr: - raise DuplicateStartAddressRecordError(line=line) - self.start_addr = {'CS': bin[4]*256 + bin[5], - 'IP': bin[6]*256 + bin[7], - } - - elif record_type == 5: - # Start Linear Address Record - if record_length != 4 or addr != 0: - raise StartLinearAddressRecordError(line=line) - if self.start_addr: - raise DuplicateStartAddressRecordError(line=line) - self.start_addr = {'EIP': (bin[4]*16777216 + - bin[5]*65536 + - bin[6]*256 + - bin[7]), - } - - def loadhex(self, fobj): - """Load hex file into internal buffer. This is not necessary - if object was initialized with source set. This will overwrite - addresses if object was already initialized. - - @param fobj file name or file-like object - """ - if getattr(fobj, "read", None) is None: - fobj = open(fobj, "r") - fclose = fobj.close - else: - fclose = None - - self._offset = 0 - line = 0 - - try: - decode = self._decode_record - try: - for s in fobj: - line += 1 - decode(s, line) - except _EndOfFile: - pass - finally: - if fclose: - fclose() - - def loadbin(self, fobj, offset=0): - """Load bin file into internal buffer. Not needed if source set in - constructor. This will overwrite addresses without warning - if object was already initialized. - - @param fobj file name or file-like object - @param offset starting address offset - """ - fread = getattr(fobj, "read", None) - if fread is None: - f = open(fobj, "rb") - fread = f.read - fclose = f.close - else: - fclose = None - - try: - self.frombytes(array('B', asbytes(fread())), offset=offset) - finally: - if fclose: - fclose() - - def loadfile(self, fobj, format): - """Load data file into internal buffer. Preferred wrapper over - loadbin or loadhex. - - @param fobj file name or file-like object - @param format file format ("hex" or "bin") - """ - if format == "hex": - self.loadhex(fobj) - elif format == "bin": - self.loadbin(fobj) - else: - raise ValueError('format should be either "hex" or "bin";' - ' got %r instead' % format) - - # alias (to be consistent with method tofile) - fromfile = loadfile - - def fromdict(self, dikt): - """Load data from dictionary. Dictionary should contain int keys - representing addresses. Values should be the data to be stored in - those addresses in unsigned char form (i.e. not strings). - The dictionary may contain the key, ``start_addr`` - to indicate the starting address of the data as described in README. - - The contents of the dict will be merged with this object and will - overwrite any conflicts. This function is not necessary if the - object was initialized with source specified. - """ - s = dikt.copy() - start_addr = s.get('start_addr') - if start_addr is not None: - del s['start_addr'] - for k in dict_keys_g(s): - if type(k) not in IntTypes or k < 0: - raise ValueError('Source dictionary should have only int keys') - self._buf.update(s) - if start_addr is not None: - self.start_addr = start_addr - - def frombytes(self, bytes, offset=0): - """Load data from array or list of bytes. - Similar to loadbin() method but works directly with iterable bytes. - """ - for b in bytes: - self._buf[offset] = b - offset += 1 - - def _get_start_end(self, start=None, end=None, size=None): - """Return default values for start and end if they are None. - If this IntelHex object is empty then it's error to - invoke this method with both start and end as None. - """ - if (start,end) == (None,None) and self._buf == {}: - raise EmptyIntelHexError - if size is not None: - if None not in (start, end): - raise ValueError("tobinarray: you can't use start,end and size" - " arguments in the same time") - if (start, end) == (None, None): - start = self.minaddr() - if start is not None: - end = start + size - 1 - else: - start = end - size + 1 - if start < 0: - raise ValueError("tobinarray: invalid size (%d) " - "for given end address (%d)" % (size,end)) - else: - if start is None: - start = self.minaddr() - if end is None: - end = self.maxaddr() - if start > end: - start, end = end, start - return start, end - - def tobinarray(self, start=None, end=None, pad=_DEPRECATED, size=None): - ''' Convert this object to binary form as array. If start and end - unspecified, they will be inferred from the data. - @param start start address of output bytes. - @param end end address of output bytes (inclusive). - @param pad [DEPRECATED PARAMETER, please use self.padding instead] - fill empty spaces with this value - (if pad is None then this method uses self.padding). - @param size size of the block, used with start or end parameter. - @return array of unsigned char data. - ''' - if not isinstance(pad, _DeprecatedParam): - print ("IntelHex.tobinarray: 'pad' parameter is deprecated.") - if pad is not None: - print ("Please, use IntelHex.padding attribute instead.") - else: - print ("Please, don't pass it explicitly.") - print ("Use syntax like this: ih.tobinarray(start=xxx, end=yyy, size=zzz)") - else: - pad = None - return self._tobinarray_really(start, end, pad, size) - - def _tobinarray_really(self, start, end, pad, size): - """Return binary array.""" - if pad is None: - pad = self.padding - bin = array('B') - if self._buf == {} and None in (start, end): - return bin - if size is not None and size <= 0: - raise ValueError("tobinarray: wrong value for size") - start, end = self._get_start_end(start, end, size) - for i in range_g(start, end+1): - bin.append(self._buf.get(i, pad)) - return bin - - def tobinstr(self, start=None, end=None, pad=_DEPRECATED, size=None): - ''' Convert to binary form and return as binary string. - @param start start address of output bytes. - @param end end address of output bytes (inclusive). - @param pad [DEPRECATED PARAMETER, please use self.padding instead] - fill empty spaces with this value - (if pad is None then this method uses self.padding). - @param size size of the block, used with start or end parameter. - @return bytes string of binary data. - ''' - if not isinstance(pad, _DeprecatedParam): - print ("IntelHex.tobinstr: 'pad' parameter is deprecated.") - if pad is not None: - print ("Please, use IntelHex.padding attribute instead.") - else: - print ("Please, don't pass it explicitly.") - print ("Use syntax like this: ih.tobinstr(start=xxx, end=yyy, size=zzz)") - else: - pad = None - return self._tobinstr_really(start, end, pad, size) - - def _tobinstr_really(self, start, end, pad, size): - return array_tobytes(self._tobinarray_really(start, end, pad, size)) - - def tobinfile(self, fobj, start=None, end=None, pad=_DEPRECATED, size=None): - '''Convert to binary and write to file. - - @param fobj file name or file object for writing output bytes. - @param start start address of output bytes. - @param end end address of output bytes (inclusive). - @param pad [DEPRECATED PARAMETER, please use self.padding instead] - fill empty spaces with this value - (if pad is None then this method uses self.padding). - @param size size of the block, used with start or end parameter. - ''' - if not isinstance(pad, _DeprecatedParam): - print ("IntelHex.tobinfile: 'pad' parameter is deprecated.") - if pad is not None: - print ("Please, use IntelHex.padding attribute instead.") - else: - print ("Please, don't pass it explicitly.") - print ("Use syntax like this: ih.tobinfile(start=xxx, end=yyy, size=zzz)") - else: - pad = None - if getattr(fobj, "write", None) is None: - fobj = open(fobj, "wb") - close_fd = True - else: - close_fd = False - - fobj.write(self._tobinstr_really(start, end, pad, size)) - - if close_fd: - fobj.close() - - def todict(self): - '''Convert to python dictionary. - - @return dict suitable for initializing another IntelHex object. - ''' - r = {} - r.update(self._buf) - if self.start_addr: - r['start_addr'] = self.start_addr - return r - - def addresses(self): - '''Returns all used addresses in sorted order. - @return list of occupied data addresses in sorted order. - ''' - aa = dict_keys(self._buf) - aa.sort() - return aa - - def minaddr(self): - '''Get minimal address of HEX content. - @return minimal address or None if no data - ''' - aa = dict_keys(self._buf) - if aa == []: - return None - else: - return min(aa) - - def maxaddr(self): - '''Get maximal address of HEX content. - @return maximal address or None if no data - ''' - aa = dict_keys(self._buf) - if aa == []: - return None - else: - return max(aa) - - def __contains__(self, addr): - ''' Returns a boolean if the address is present. - @param addr address of byte. - @return bool if address exists in HEX file. - ''' - if addr < 0: - raise TypeError('Address should be >= 0.') - return addr in self._buf - - def __getitem__(self, addr): - ''' Get requested byte from address. - @param addr address of byte. - @return byte if address exists in HEX file, or self.padding - if no data found. - ''' - t = type(addr) - if t in IntTypes: - if addr < 0: - raise TypeError('Address should be >= 0.') - addresses = dict_keys(self._buf) - if not addresses or addr > max(addresses): - raise IndexError - return self._buf.get(addr, self.padding) - elif t == slice: - addresses = dict_keys(self._buf) - ih = IntelHex() - if addresses: - addresses.sort() - start = addr.start if addr.start is not None else addresses[0] - stop = addr.stop if addr.stop is not None else addresses[-1] + 1 - step = addr.step or 1 - for i in range_g(start, stop, step): - x = self._buf.get(i) - if x is not None: - ih[i] = x - return ih - else: - raise TypeError('Address has unsupported type: %s' % t) - - def __setitem__(self, addr, byte): - """Set byte at address.""" - t = type(addr) - if t in IntTypes: - if addr < 0: - raise TypeError('Address should be >= 0.') - self._buf[addr] = byte - elif t == slice: - if not isinstance(byte, (list, tuple)): - raise ValueError('Slice operation expects sequence of bytes') - start = addr.start - stop = addr.stop - step = addr.step or 1 - if None not in (start, stop): - ra = range_l(start, stop, step) - if len(ra) != len(byte): - raise ValueError('Length of bytes sequence does not match ' - 'address range') - elif (start, stop) == (None, None): - raise TypeError('Unsupported address range') - elif start is None: - start = stop - len(byte) - elif stop is None: - stop = start + len(byte) - if start < 0: - raise TypeError('start address cannot be negative') - if stop < 0: - raise TypeError('stop address cannot be negative') - j = 0 - for i in range_g(start, stop, step): - self._buf[i] = byte[j] - j += 1 - else: - raise TypeError('Address has unsupported type: %s' % t) - - def __delitem__(self, addr): - """Delete byte at address.""" - t = type(addr) - if t in IntTypes: - if addr < 0: - raise TypeError('Address should be >= 0.') - del self._buf[addr] - elif t == slice: - addresses = dict_keys(self._buf) - if addresses: - addresses.sort() - start = addr.start or addresses[0] - stop = addr.stop or (addresses[-1]+1) - step = addr.step or 1 - for i in range_g(start, stop, step): - x = self._buf.get(i) - if x is not None: - del self._buf[i] - else: - raise TypeError('Address has unsupported type: %s' % t) - - def __len__(self): - """Return count of bytes with real values.""" - return len(dict_keys(self._buf)) - - def _get_eol_textfile(eolstyle, platform): - if eolstyle == 'native': - return '\n' - elif eolstyle == 'CRLF': - if platform != 'win32': - return '\r\n' - else: - return '\n' - else: - raise ValueError("wrong eolstyle %s" % repr(eolstyle)) - _get_eol_textfile = staticmethod(_get_eol_textfile) - - def write_hex_file(self, f, write_start_addr=True, eolstyle='native', byte_count=16): - """Write data to file f in HEX format. - - @param f filename or file-like object for writing - @param write_start_addr enable or disable writing start address - record to file (enabled by default). - If there is no start address in obj, nothing - will be written regardless of this setting. - @param eolstyle can be used to force CRLF line-endings - for output file on different platforms. - Supported eol styles: 'native', 'CRLF'. - @param byte_count number of bytes in the data field - """ - if byte_count > 255 or byte_count < 1: - raise ValueError("wrong byte_count value: %s" % byte_count) - fwrite = getattr(f, "write", None) - if fwrite: - fobj = f - fclose = None - else: - fobj = open(f, 'w') - fwrite = fobj.write - fclose = fobj.close - - eol = IntelHex._get_eol_textfile(eolstyle, sys.platform) - - # Translation table for uppercasing hex ascii string. - # timeit shows that using hexstr.translate(table) - # is faster than hexstr.upper(): - # 0.452ms vs. 0.652ms (translate vs. upper) - if sys.version_info[0] >= 3: - # Python 3 - table = bytes(range_l(256)).upper() - else: - # Python 2 - table = ''.join(chr(i).upper() for i in range_g(256)) - - # start address record if any - if self.start_addr and write_start_addr: - keys = dict_keys(self.start_addr) - keys.sort() - bin = array('B', asbytes('\0'*9)) - if keys == ['CS','IP']: - # Start Segment Address Record - bin[0] = 4 # reclen - bin[1] = 0 # offset msb - bin[2] = 0 # offset lsb - bin[3] = 3 # rectyp - cs = self.start_addr['CS'] - bin[4] = (cs >> 8) & 0x0FF - bin[5] = cs & 0x0FF - ip = self.start_addr['IP'] - bin[6] = (ip >> 8) & 0x0FF - bin[7] = ip & 0x0FF - bin[8] = (-sum(bin)) & 0x0FF # chksum - fwrite(':' + - asstr(hexlify(array_tobytes(bin)).translate(table)) + - eol) - elif keys == ['EIP']: - # Start Linear Address Record - bin[0] = 4 # reclen - bin[1] = 0 # offset msb - bin[2] = 0 # offset lsb - bin[3] = 5 # rectyp - eip = self.start_addr['EIP'] - bin[4] = (eip >> 24) & 0x0FF - bin[5] = (eip >> 16) & 0x0FF - bin[6] = (eip >> 8) & 0x0FF - bin[7] = eip & 0x0FF - bin[8] = (-sum(bin)) & 0x0FF # chksum - fwrite(':' + - asstr(hexlify(array_tobytes(bin)).translate(table)) + - eol) - else: - if fclose: - fclose() - raise InvalidStartAddressValueError(start_addr=self.start_addr) - - # data - addresses = dict_keys(self._buf) - addresses.sort() - addr_len = len(addresses) - if addr_len: - minaddr = addresses[0] - maxaddr = addresses[-1] - - if maxaddr > 65535: - need_offset_record = True - else: - need_offset_record = False - high_ofs = 0 - - cur_addr = minaddr - cur_ix = 0 - - while cur_addr <= maxaddr: - if need_offset_record: - bin = array('B', asbytes('\0'*7)) - bin[0] = 2 # reclen - bin[1] = 0 # offset msb - bin[2] = 0 # offset lsb - bin[3] = 4 # rectyp - high_ofs = int(cur_addr>>16) - b = divmod(high_ofs, 256) - bin[4] = b[0] # msb of high_ofs - bin[5] = b[1] # lsb of high_ofs - bin[6] = (-sum(bin)) & 0x0FF # chksum - fwrite(':' + - asstr(hexlify(array_tobytes(bin)).translate(table)) + - eol) - - while True: - # produce one record - low_addr = cur_addr & 0x0FFFF - # chain_len off by 1 - chain_len = min(byte_count-1, 65535-low_addr, maxaddr-cur_addr) - - # search continuous chain - stop_addr = cur_addr + chain_len - if chain_len: - ix = bisect_right(addresses, stop_addr, - cur_ix, - min(cur_ix+chain_len+1, addr_len)) - chain_len = ix - cur_ix # real chain_len - # there could be small holes in the chain - # but we will catch them by try-except later - # so for big continuous files we will work - # at maximum possible speed - else: - chain_len = 1 # real chain_len - - bin = array('B', asbytes('\0'*(5+chain_len))) - b = divmod(low_addr, 256) - bin[1] = b[0] # msb of low_addr - bin[2] = b[1] # lsb of low_addr - bin[3] = 0 # rectype - try: # if there is small holes we'll catch them - for i in range_g(chain_len): - bin[4+i] = self._buf[cur_addr+i] - except KeyError: - # we catch a hole so we should shrink the chain - chain_len = i - bin = bin[:5+i] - bin[0] = chain_len - bin[4+chain_len] = (-sum(bin)) & 0x0FF # chksum - fwrite(':' + - asstr(hexlify(array_tobytes(bin)).translate(table)) + - eol) - - # adjust cur_addr/cur_ix - cur_ix += chain_len - if cur_ix < addr_len: - cur_addr = addresses[cur_ix] - else: - cur_addr = maxaddr + 1 - break - high_addr = int(cur_addr>>16) - if high_addr > high_ofs: - break - - # end-of-file record - fwrite(":00000001FF"+eol) - if fclose: - fclose() - - def tofile(self, fobj, format, byte_count=16): - """Write data to hex or bin file. Preferred method over tobin or tohex. - - @param fobj file name or file-like object - @param format file format ("hex" or "bin") - @param byte_count bytes per line - """ - if format == 'hex': - self.write_hex_file(fobj, byte_count=byte_count) - elif format == 'bin': - self.tobinfile(fobj) - else: - raise ValueError('format should be either "hex" or "bin";' - ' got %r instead' % format) - - def gets(self, addr, length): - """Get string of bytes from given address. If any entries are blank - from addr through addr+length, a NotEnoughDataError exception will - be raised. Padding is not used. - """ - a = array('B', asbytes('\0'*length)) - try: - for i in range_g(length): - a[i] = self._buf[addr+i] - except KeyError: - raise NotEnoughDataError(address=addr, length=length) - return array_tobytes(a) - - def puts(self, addr, s): - """Put string of bytes at given address. Will overwrite any previous - entries. - """ - a = array('B', asbytes(s)) - for i in range_g(len(a)): - self._buf[addr+i] = a[i] - - def getsz(self, addr): - """Get zero-terminated bytes string from given address. Will raise - NotEnoughDataError exception if a hole is encountered before a 0. - """ - i = 0 - try: - while True: - if self._buf[addr+i] == 0: - break - i += 1 - except KeyError: - raise NotEnoughDataError(msg=('Bad access at 0x%X: ' - 'not enough data to read zero-terminated string') % addr) - return self.gets(addr, i) - - def putsz(self, addr, s): - """Put bytes string in object at addr and append terminating zero at end.""" - self.puts(addr, s) - self._buf[addr+len(s)] = 0 - - def find(self, sub, start=None, end=None): - """Return the lowest index in self[start:end] where subsection sub is found. - Optional arguments start and end are interpreted as in slice notation. - - @param sub bytes-like subsection to find - @param start start of section to search within (optional) - @param end end of section to search within (optional) - """ - sub = bytes(sub) - for start, end in self[slice(start,end)].segments(): - b = self.gets(start, end-start) - i = b.find(sub) - if i != -1: - return start+i - return -1 - - def dump(self, tofile=None, width=16, withpadding=False): - """Dump object content to specified file object or to stdout if None. - Format is a hexdump with some header information at the beginning, - addresses on the left, and data on right. - - @param tofile file-like object to dump to - @param width number of bytes per line (i.e. columns) - @param withpadding print padding character instead of '--' - @raise ValueError if width is not a positive integer - """ - - if not isinstance(width,int) or width < 1: - raise ValueError('width must be a positive integer.') - # The integer can be of float type - does not work with bit operations - width = int(width) - if tofile is None: - tofile = sys.stdout - - # start addr possibly - if self.start_addr is not None: - cs = self.start_addr.get('CS') - ip = self.start_addr.get('IP') - eip = self.start_addr.get('EIP') - if eip is not None and cs is None and ip is None: - tofile.write('EIP = 0x%08X\n' % eip) - elif eip is None and cs is not None and ip is not None: - tofile.write('CS = 0x%04X, IP = 0x%04X\n' % (cs, ip)) - else: - tofile.write('start_addr = %r\n' % self.start_addr) - # actual data - addresses = dict_keys(self._buf) - if addresses: - addresses.sort() - minaddr = addresses[0] - maxaddr = addresses[-1] - startaddr = (minaddr // width) * width - endaddr = ((maxaddr // width) + 1) * width - maxdigits = max(len(hex(endaddr)) - 2, 4) # Less 2 to exclude '0x' - templa = '%%0%dX' % maxdigits - rangewidth = range_l(width) - if withpadding: - pad = self.padding - else: - pad = None - for i in range_g(startaddr, endaddr, width): - tofile.write(templa % i) - tofile.write(' ') - s = [] - for j in rangewidth: - x = self._buf.get(i+j, pad) - if x is not None: - tofile.write(' %02X' % x) - if 32 <= x < 127: # GNU less does not like 0x7F (128 decimal) so we'd better show it as dot - s.append(chr(x)) - else: - s.append('.') - else: - tofile.write(' --') - s.append(' ') - tofile.write(' |' + ''.join(s) + '|\n') - - def merge(self, other, overlap='error'): - """Merge content of other IntelHex object into current object (self). - @param other other IntelHex object. - @param overlap action on overlap of data or starting addr: - - error: raising OverlapError; - - ignore: ignore other data and keep current data - in overlapping region; - - replace: replace data with other data - in overlapping region. - - @raise TypeError if other is not instance of IntelHex - @raise ValueError if other is the same object as self - (it can't merge itself) - @raise ValueError if overlap argument has incorrect value - @raise AddressOverlapError on overlapped data - """ - # check args - if not isinstance(other, IntelHex): - raise TypeError('other should be IntelHex object') - if other is self: - raise ValueError("Can't merge itself") - if overlap not in ('error', 'ignore', 'replace'): - raise ValueError("overlap argument should be either " - "'error', 'ignore' or 'replace'") - # merge data - this_buf = self._buf - other_buf = other._buf - for i in other_buf: - if i in this_buf: - if overlap == 'error': - raise AddressOverlapError( - 'Data overlapped at address 0x%X' % i) - elif overlap == 'ignore': - continue - this_buf[i] = other_buf[i] - # merge start_addr - if self.start_addr != other.start_addr: - if self.start_addr is None: # set start addr from other - self.start_addr = other.start_addr - elif other.start_addr is None: # keep existing start addr - pass - else: # conflict - if overlap == 'error': - raise AddressOverlapError( - 'Starting addresses are different') - elif overlap == 'replace': - self.start_addr = other.start_addr - - def segments(self, min_gap=1): - """Return a list of ordered tuple objects, representing contiguous occupied data addresses. - Each tuple has a length of two and follows the semantics of the range and xrange objects. - The second entry of the tuple is always an integer greater than the first entry. - @param min_gap the minimum gap size between data in order to separate the segments - """ - addresses = self.addresses() - if not addresses: - return [] - elif len(addresses) == 1: - return([(addresses[0], addresses[0]+1)]) - adjacent_differences = [(b - a) for (a, b) in zip(addresses[:-1], addresses[1:])] - breaks = [i for (i, x) in enumerate(adjacent_differences) if x > min_gap] - endings = [addresses[b] for b in breaks] - endings.append(addresses[-1]) - beginnings = [addresses[b+1] for b in breaks] - beginnings.insert(0, addresses[0]) - return [(a, b+1) for (a, b) in zip(beginnings, endings)] - - def get_memory_size(self): - """Returns the approximate memory footprint for data.""" - n = sys.getsizeof(self) - n += sys.getsizeof(self.padding) - n += total_size(self.start_addr) - n += total_size(self._buf) - n += sys.getsizeof(self._offset) - return n - -#/IntelHex - - -class IntelHex16bit(IntelHex): - """Access to data as 16-bit words. Intended to use with Microchip HEX files.""" - - def __init__(self, source=None): - """Construct class from HEX file - or from instance of ordinary IntelHex class. If IntelHex object - is passed as source, the original IntelHex object should not be used - again because this class will alter it. This class leaves padding - alone unless it was precisely 0xFF. In that instance it is sign - extended to 0xFFFF. - - @param source file name of HEX file or file object - or instance of ordinary IntelHex class. - Will also accept dictionary from todict method. - """ - if isinstance(source, IntelHex): - # from ihex8 - self.padding = source.padding - self.start_addr = source.start_addr - # private members - self._buf = source._buf - self._offset = source._offset - elif isinstance(source, dict): - raise IntelHexError("IntelHex16bit does not support initialization from dictionary yet.\n" - "Patches are welcome.") - else: - IntelHex.__init__(self, source) - - if self.padding == 0x0FF: - self.padding = 0x0FFFF - - def __getitem__(self, addr16): - """Get 16-bit word from address. - Raise error if only one byte from the pair is set. - We assume a Little Endian interpretation of the hex file. - - @param addr16 address of word (addr8 = 2 * addr16). - @return word if bytes exists in HEX file, or self.padding - if no data found. - """ - addr1 = addr16 * 2 - addr2 = addr1 + 1 - byte1 = self._buf.get(addr1, None) - byte2 = self._buf.get(addr2, None) - - if byte1 != None and byte2 != None: - return byte1 | (byte2 << 8) # low endian - - if byte1 == None and byte2 == None: - return self.padding - - raise BadAccess16bit(address=addr16) - - def __setitem__(self, addr16, word): - """Sets the address at addr16 to word assuming Little Endian mode. - """ - addr_byte = addr16 * 2 - b = divmod(word, 256) - self._buf[addr_byte] = b[1] - self._buf[addr_byte+1] = b[0] - - def minaddr(self): - '''Get minimal address of HEX content in 16-bit mode. - - @return minimal address used in this object - ''' - aa = dict_keys(self._buf) - if aa == []: - return 0 - else: - return min(aa)>>1 - - def maxaddr(self): - '''Get maximal address of HEX content in 16-bit mode. - - @return maximal address used in this object - ''' - aa = dict_keys(self._buf) - if aa == []: - return 0 - else: - return max(aa)>>1 - - def tobinarray(self, start=None, end=None, size=None): - '''Convert this object to binary form as array (of 2-bytes word data). - If start and end unspecified, they will be inferred from the data. - @param start start address of output data. - @param end end address of output data (inclusive). - @param size size of the block (number of words), - used with start or end parameter. - @return array of unsigned short (uint16_t) data. - ''' - bin = array('H') - - if self._buf == {} and None in (start, end): - return bin - - if size is not None and size <= 0: - raise ValueError("tobinarray: wrong value for size") - - start, end = self._get_start_end(start, end, size) - - for addr in range_g(start, end+1): - bin.append(self[addr]) - - return bin - - -#/class IntelHex16bit - - -def hex2bin(fin, fout, start=None, end=None, size=None, pad=None): - """Hex-to-Bin convertor engine. - @return 0 if all OK - - @param fin input hex file (filename or file-like object) - @param fout output bin file (filename or file-like object) - @param start start of address range (optional) - @param end end of address range (inclusive; optional) - @param size size of resulting file (in bytes) (optional) - @param pad padding byte (optional) - """ - try: - h = IntelHex(fin) - except HexReaderError: - e = sys.exc_info()[1] # current exception - txt = "ERROR: bad HEX file: %s" % str(e) - print(txt) - return 1 - - # start, end, size - if size != None and size != 0: - if end == None: - if start == None: - start = h.minaddr() - end = start + size - 1 - else: - if (end+1) >= size: - start = end + 1 - size - else: - start = 0 - - try: - if pad is not None: - # using .padding attribute rather than pad argument to function call - h.padding = pad - h.tobinfile(fout, start, end) - except IOError: - e = sys.exc_info()[1] # current exception - txt = "ERROR: Could not write to file: %s: %s" % (fout, str(e)) - print(txt) - return 1 - - return 0 -#/def hex2bin - - -def bin2hex(fin, fout, offset=0): - """Simple bin-to-hex convertor. - @return 0 if all OK - - @param fin input bin file (filename or file-like object) - @param fout output hex file (filename or file-like object) - @param offset starting address offset for loading bin - """ - h = IntelHex() - try: - h.loadbin(fin, offset) - except IOError: - e = sys.exc_info()[1] # current exception - txt = 'ERROR: unable to load bin file:', str(e) - print(txt) - return 1 - - try: - h.tofile(fout, format='hex') - except IOError: - e = sys.exc_info()[1] # current exception - txt = "ERROR: Could not write to file: %s: %s" % (fout, str(e)) - print(txt) - return 1 - - return 0 -#/def bin2hex - - -def diff_dumps(ih1, ih2, tofile=None, name1="a", name2="b", n_context=3): - """Diff 2 IntelHex objects and produce unified diff output for their - hex dumps. - - @param ih1 first IntelHex object to compare - @param ih2 second IntelHex object to compare - @param tofile file-like object to write output - @param name1 name of the first hex file to show in the diff header - @param name2 name of the first hex file to show in the diff header - @param n_context number of context lines in the unidiff output - """ - def prepare_lines(ih): - sio = StringIO() - ih.dump(sio) - dump = sio.getvalue() - lines = dump.splitlines() - return lines - a = prepare_lines(ih1) - b = prepare_lines(ih2) - import difflib - result = list(difflib.unified_diff(a, b, fromfile=name1, tofile=name2, n=n_context, lineterm='')) - if tofile is None: - tofile = sys.stdout - output = '\n'.join(result)+'\n' - tofile.write(output) - - -class Record(object): - """Helper methods to build valid ihex records.""" - - def _from_bytes(bytes): - """Takes a list of bytes, computes the checksum, and outputs the entire - record as a string. bytes should be the hex record without the colon - or final checksum. - - @param bytes list of byte values so far to pack into record. - @return String representation of one HEX record - """ - assert len(bytes) >= 4 - # calculate checksum - s = (-sum(bytes)) & 0x0FF - bin = array('B', bytes + [s]) - return ':' + asstr(hexlify(array_tobytes(bin))).upper() - _from_bytes = staticmethod(_from_bytes) - - def data(offset, bytes): - """Return Data record. This constructs the full record, including - the length information, the record type (0x00), the - checksum, and the offset. - - @param offset load offset of first byte. - @param bytes list of byte values to pack into record. - - @return String representation of one HEX record - """ - assert 0 <= offset < 65536 - assert 0 < len(bytes) < 256 - b = [len(bytes), (offset>>8)&0x0FF, offset&0x0FF, 0x00] + bytes - return Record._from_bytes(b) - data = staticmethod(data) - - def eof(): - """Return End of File record as a string. - @return String representation of Intel Hex EOF record - """ - return ':00000001FF' - eof = staticmethod(eof) - - def extended_segment_address(usba): - """Return Extended Segment Address Record. - @param usba Upper Segment Base Address. - - @return String representation of Intel Hex USBA record. - """ - b = [2, 0, 0, 0x02, (usba>>8)&0x0FF, usba&0x0FF] - return Record._from_bytes(b) - extended_segment_address = staticmethod(extended_segment_address) - - def start_segment_address(cs, ip): - """Return Start Segment Address Record. - @param cs 16-bit value for CS register. - @param ip 16-bit value for IP register. - - @return String representation of Intel Hex SSA record. - """ - b = [4, 0, 0, 0x03, (cs>>8)&0x0FF, cs&0x0FF, - (ip>>8)&0x0FF, ip&0x0FF] - return Record._from_bytes(b) - start_segment_address = staticmethod(start_segment_address) - - def extended_linear_address(ulba): - """Return Extended Linear Address Record. - @param ulba Upper Linear Base Address. - - @return String representation of Intel Hex ELA record. - """ - b = [2, 0, 0, 0x04, (ulba>>8)&0x0FF, ulba&0x0FF] - return Record._from_bytes(b) - extended_linear_address = staticmethod(extended_linear_address) - - def start_linear_address(eip): - """Return Start Linear Address Record. - @param eip 32-bit linear address for the EIP register. - - @return String representation of Intel Hex SLA record. - """ - b = [4, 0, 0, 0x05, (eip>>24)&0x0FF, (eip>>16)&0x0FF, - (eip>>8)&0x0FF, eip&0x0FF] - return Record._from_bytes(b) - start_linear_address = staticmethod(start_linear_address) - - -class _BadFileNotation(Exception): - """Special error class to use with _get_file_and_addr_range.""" - pass - -def _get_file_and_addr_range(s, _support_drive_letter=None): - """Special method for hexmerge.py script to split file notation - into 3 parts: (filename, start, end) - - @raise _BadFileNotation when string cannot be safely split. - """ - if _support_drive_letter is None: - _support_drive_letter = (os.name == 'nt') - drive = '' - if _support_drive_letter: - if s[1:2] == ':' and s[0].upper() in ''.join([chr(i) for i in range_g(ord('A'), ord('Z')+1)]): - drive = s[:2] - s = s[2:] - parts = s.split(':') - n = len(parts) - if n == 1: - fname = parts[0] - fstart = None - fend = None - elif n != 3: - raise _BadFileNotation - else: - fname = parts[0] - def ascii_hex_to_int(ascii): - if ascii is not None: - try: - return int(ascii, 16) - except ValueError: - raise _BadFileNotation - return ascii - fstart = ascii_hex_to_int(parts[1] or None) - fend = ascii_hex_to_int(parts[2] or None) - return drive+fname, fstart, fend - - -## -# IntelHex Errors Hierarchy: -# -# IntelHexError - basic error -# HexReaderError - general hex reader error -# AddressOverlapError - data for the same address overlap -# HexRecordError - hex record decoder base error -# RecordLengthError - record has invalid length -# RecordTypeError - record has invalid type (RECTYP) -# RecordChecksumError - record checksum mismatch -# EOFRecordError - invalid EOF record (type 01) -# ExtendedAddressRecordError - extended address record base error -# ExtendedSegmentAddressRecordError - invalid extended segment address record (type 02) -# ExtendedLinearAddressRecordError - invalid extended linear address record (type 04) -# StartAddressRecordError - start address record base error -# StartSegmentAddressRecordError - invalid start segment address record (type 03) -# StartLinearAddressRecordError - invalid start linear address record (type 05) -# DuplicateStartAddressRecordError - start address record appears twice -# InvalidStartAddressValueError - invalid value of start addr record -# _EndOfFile - it's not real error, used internally by hex reader as signal that EOF record found -# BadAccess16bit - not enough data to read 16 bit value (deprecated, see NotEnoughDataError) -# NotEnoughDataError - not enough data to read N contiguous bytes -# EmptyIntelHexError - requested operation cannot be performed with empty object - -class IntelHexError(Exception): - '''Base Exception class for IntelHex module''' - - _fmt = 'IntelHex base error' #: format string - - def __init__(self, msg=None, **kw): - """Initialize the Exception with the given message. - """ - self.msg = msg - for key, value in dict_items_g(kw): - setattr(self, key, value) - - def __str__(self): - """Return the message in this Exception.""" - if self.msg: - return self.msg - try: - return self._fmt % self.__dict__ - except (NameError, ValueError, KeyError): - e = sys.exc_info()[1] # current exception - return 'Unprintable exception %s: %s' \ - % (repr(e), str(e)) - -class _EndOfFile(IntelHexError): - """Used for internal needs only.""" - _fmt = 'EOF record reached -- signal to stop read file' - -class HexReaderError(IntelHexError): - _fmt = 'Hex reader base error' - -class AddressOverlapError(HexReaderError): - _fmt = 'Hex file has data overlap at address 0x%(address)X on line %(line)d' - -# class NotAHexFileError was removed in trunk.revno.54 because it's not used - - -class HexRecordError(HexReaderError): - _fmt = 'Hex file contains invalid record at line %(line)d' - - -class RecordLengthError(HexRecordError): - _fmt = 'Record at line %(line)d has invalid length' - -class RecordTypeError(HexRecordError): - _fmt = 'Record at line %(line)d has invalid record type' - -class RecordChecksumError(HexRecordError): - _fmt = 'Record at line %(line)d has invalid checksum' - -class EOFRecordError(HexRecordError): - _fmt = 'File has invalid End-of-File record' - - -class ExtendedAddressRecordError(HexRecordError): - _fmt = 'Base class for extended address exceptions' - -class ExtendedSegmentAddressRecordError(ExtendedAddressRecordError): - _fmt = 'Invalid Extended Segment Address Record at line %(line)d' - -class ExtendedLinearAddressRecordError(ExtendedAddressRecordError): - _fmt = 'Invalid Extended Linear Address Record at line %(line)d' - - -class StartAddressRecordError(HexRecordError): - _fmt = 'Base class for start address exceptions' - -class StartSegmentAddressRecordError(StartAddressRecordError): - _fmt = 'Invalid Start Segment Address Record at line %(line)d' - -class StartLinearAddressRecordError(StartAddressRecordError): - _fmt = 'Invalid Start Linear Address Record at line %(line)d' - -class DuplicateStartAddressRecordError(StartAddressRecordError): - _fmt = 'Start Address Record appears twice at line %(line)d' - -class InvalidStartAddressValueError(StartAddressRecordError): - _fmt = 'Invalid start address value: %(start_addr)s' - - -class NotEnoughDataError(IntelHexError): - _fmt = ('Bad access at 0x%(address)X: ' - 'not enough data to read %(length)d contiguous bytes') - -class BadAccess16bit(NotEnoughDataError): - _fmt = 'Bad access at 0x%(address)X: not enough data to read 16 bit value' - -class EmptyIntelHexError(IntelHexError): - _fmt = "Requested operation cannot be executed with empty object" diff --git a/intelhex/__main__.py b/intelhex/__main__.py deleted file mode 100644 index bb9d559..0000000 --- a/intelhex/__main__.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2016-2018, Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -if __name__ == '__main__': - print("Welcome to IntelHex Python library.") - print() - print("The intelhex package has some executable points:") - print(" python -m intelhex.test -- easy way to run unit tests.") - print(" python -m intelhex.bench -- run benchmarks.") diff --git a/intelhex/__version__.py b/intelhex/__version__.py deleted file mode 100644 index 3ad5f13..0000000 --- a/intelhex/__version__.py +++ /dev/null @@ -1,3 +0,0 @@ -# IntelHex library version information -version_info = (2, 3, 0) -version_str = '.'.join([str(i) for i in version_info]) diff --git a/intelhex/bench.py b/intelhex/bench.py deleted file mode 100644 index 7586e2c..0000000 --- a/intelhex/bench.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/env python -# (c) Alexander Belchenko, 2007, 2009 - -# [2013/08] NOTE: This file is keeping for historical reasons. -# It may or may not work actually with current version of intelhex, -# and most likely it requires some fixes here and there. - -"""Benchmarking. - -Run each test 3 times and get median value. -Using 10K array as base test time. - -Each other test compared with base with next formula:: - - Tc * Nb - q = --------- - Tb * Nc - -Here: - -* Tc - execution time of current test -* Tb - execution time of base -* Nb - array size of base (10K) -* Nc - array size of current test - -If resulting value is ``q <= 1.0`` it's the best possible result, -i.e. time increase proportionally to array size. -""" - -import gc -import sys -import time - -import intelhex -from intelhex.compat import StringIO, range_g - -def median(values): - """Return median value for the list of values. - @param values: list of values for processing. - @return: median value. - """ - values.sort() - n = int(len(values) / 2) - return values[n] - -def run_test(func, fobj): - """Run func with argument fobj and measure execution time. - @param func: function for test - @param fobj: data for test - @return: execution time - """ - gc.disable() - try: - begin = time.time() - func(fobj) - end = time.time() - finally: - gc.enable() - return end - begin - -def run_readtest_N_times(func, hexstr, n): - """Run each test N times. - @param func: function for test - @param hexstr: string with content of hex file to read - @param n: times to repeat. - @return: (median time, times list) - """ - assert n > 0 - times = [] - for i in range_g(n): - sio = StringIO(hexstr) - times.append(run_test(func, sio)) - sio.close() - t = median(times) - return t, times - -def run_writetest_N_times(func, n): - """Run each test N times. - @param func: function for test - @param n: times to repeat. - @return: (median time, times list) - """ - assert n > 0 - times = [] - for i in range_g(n): - sio = StringIO() - times.append(run_test(func, sio)) - sio.close() - t = median(times) - return t, times - -def time_coef(tc, nc, tb, nb): - """Return time coefficient relative to base numbers. - @param tc: current test time - @param nc: current test data size - @param tb: base test time - @param nb: base test data size - @return: time coef. - """ - tc = float(tc) - nc = float(nc) - tb = float(tb) - nb = float(nb) - q = (tc * nb) / (tb * nc) - return q - -def get_test_data(n1, offset, n2): - """Create test data on given pattern. - @param n1: size of first part of array at base address 0. - @param offset: offset for second part of array. - @param n2: size of second part of array at given offset. - @return: (overall size, hex file, IntelHex object) - """ - # make IntelHex object - ih = intelhex.IntelHex() - addr = 0 - for i in range_g(n1): - ih[addr] = addr % 256 - addr += 1 - addr += offset - for i in range_g(n2): - ih[addr] = addr % 256 - addr += 1 - # make hex file - sio = StringIO() - ih.write_hex_file(sio) - hexstr = sio.getvalue() - sio.close() - # - return n1+n2, hexstr, ih - -def get_base_50K(): - return get_test_data(50000, 0, 0) - -def get_250K(): - return get_test_data(250000, 0, 0) - -def get_100K_100K(): - return get_test_data(100000, 1000000, 100000) - -def get_0_100K(): - return get_test_data(0, 1000000, 100000) - -def get_1M(): - return get_test_data(1000000, 0, 0) - - -class Measure(object): - """Measure execution time helper.""" - - data_set = [ - # (data name, getter) - ('base 50K', get_base_50K), # first should be base numbers - ('250K', get_250K), - ('1M', get_1M), - ('100K+100K', get_100K_100K), - ('0+100K', get_0_100K), - ] - - def __init__(self, n=3, read=True, write=True): - self.n = n - self.read = read - self.write = write - self.results = [] - - def measure_one(self, data): - """Do measuring of read and write operations. - @param data: 3-tuple from get_test_data - @return: (time readhex, time writehex) - """ - _unused, hexstr, ih = data - tread, twrite = 0.0, 0.0 - if self.read: - tread = run_readtest_N_times(intelhex.IntelHex, hexstr, self.n)[0] - if self.write: - twrite = run_writetest_N_times(ih.write_hex_file, self.n)[0] - return tread, twrite - - def measure_all(self): - for name, getter in self.data_set: - data = getter() - times = self.measure_one(data) - self.results.append((name, times, data[0])) - - def print_report(self, to_file=None): - if to_file is None: - to_file = sys.stdout - - base_title, base_times, base_n = self.results[0] - base_read, base_write = base_times - read_report = ['%-10s\t%7.3f' % (base_title, base_read)] - write_report = ['%-10s\t%7.3f' % (base_title, base_write)] - - for item in self.results[1:]: - cur_title, cur_times, cur_n = item - cur_read, cur_write = cur_times - if self.read: - qread = time_coef(cur_read, cur_n, - base_read, base_n) - read_report.append('%-10s\t%7.3f\t%7.3f' % (cur_title, - cur_read, - qread)) - if self.write: - qwrite = time_coef(cur_write, cur_n, - base_write, base_n) - write_report.append('%-10s\t%7.3f\t%7.3f' % (cur_title, - cur_write, - qwrite)) - if self.read: - to_file.write('Read operation:\n') - to_file.write('\n'.join(read_report)) - to_file.write('\n\n') - if self.write: - to_file.write('Write operation:\n') - to_file.write('\n'.join(write_report)) - to_file.write('\n\n') - - -HELP = """\ -Usage: python _bench.py [OPTIONS] - -Options: - -h this help - -n N repeat tests N times - -r run only tests for read operation - -w run only tests for write operation - -If option -r or -w is not specified then all tests will be run. -""" - - -def main(argv=None): - """Main function to run benchmarks. - @param argv: command-line arguments. - @return: exit code (0 is OK). - """ - import getopt - - # default values - test_read = None - test_write = None - n = 3 # number of repeat - - if argv is None: - argv = sys.argv[1:] - - try: - opts, args = getopt.getopt(argv, 'hn:rw', []) - - for o,a in opts: - if o == '-h': - print(HELP) - return 0 - elif o == '-n': - n = int(a) - elif o == '-r': - test_read = True - elif o == '-w': - test_write = True - - if args: - raise getopt.GetoptError('Arguments are not used.') - except getopt.GetoptError: - msg = sys.exc_info()[1] # current exception - txt = str(msg) - print(txt) - return 1 - - if (test_read, test_write) == (None, None): - test_read = test_write = True - - m = Measure(n, test_read, test_write) - m.measure_all() - m.print_report() - - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) - - -""" - -Some Results -************ - - -21/04/2007 revno.40 -Python 2.5 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz - -Read operation: -base 10K 0.031 -100K 0.360 1.161 -1M 3.500 1.129 -100K+100K 0.719 1.160 -0+100K 0.360 1.161 - -Write operation: -base 10K 0.031 -100K 0.297 0.958 -1M 2.953 0.953 -100K+100K 1.328 2.142 -0+100K 0.312 1.006 - - -21/04/2007 revno.46 -Python 2.5 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz - -Read operation: -base 10K 0.016 -100K 0.203 1.269 -1M 2.000 1.250 -100K+100K 0.422 1.319 -0+100K 0.203 1.269 - -Write operation: -base 10K 0.031 -100K 0.297 0.958 -1M 2.969 0.958 -100K+100K 1.328 2.142 -0+100K 0.312 1.006 - - -22/04/2007 revno.48 -Python 2.5 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz - -Read operation: -base 10K 0.016 -100K 0.187 1.169 -1M 1.891 1.182 -100K+100K 0.406 1.269 -0+100K 0.188 1.175 - -Write operation: -base 10K 0.031 -100K 0.296 0.955 -1M 2.969 0.958 -100K+100K 1.328 2.142 -0+100K 0.312 1.006 - - -19/08/2008 revno.72 -Python 2.5.2 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz - -Read operation: -base 10K 0.016 -100K 0.171 1.069 -1M 1.734 1.084 -100K+100K 0.375 1.172 -0+100K 0.172 1.075 - -Write operation: -base 10K 0.016 -100K 0.156 0.975 -1M 1.532 0.957 -100K+100K 0.344 1.075 -0+100K 0.156 0.975 - -""" diff --git a/intelhex/compat.py b/intelhex/compat.py deleted file mode 100644 index 2a6bee6..0000000 --- a/intelhex/compat.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright (c) 2011, Bernhard Leiner -# Copyright (c) 2013-2018 Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -'''Compatibility functions for python 2 and 3. - -@author Bernhard Leiner (bleiner AT gmail com) -@author Alexander Belchenko (alexander belchenko AT gmail com) -''' - -__docformat__ = "javadoc" - - -import sys, array - - -if sys.version_info[0] >= 3: - # Python 3 - Python = 3 - - def asbytes(s): - if isinstance(s, bytes): - return s - return s.encode('latin1') - def asstr(s): - if isinstance(s, str): - return s - return s.decode('latin1') - - # for python >= 3.2 use 'tobytes', otherwise 'tostring' - array_tobytes = array.array.tobytes if sys.version_info[1] >= 2 else array.array.tostring - - IntTypes = (int,) - StrType = str - UnicodeType = str - - range_g = range # range generator - def range_l(*args): # range list - return list(range(*args)) - - def dict_keys(dikt): # dict keys list - return list(dikt.keys()) - def dict_keys_g(dikt): # dict keys generator - return dikt.keys() - def dict_items_g(dikt): # dict items generator - return dikt.items() - - from io import StringIO, BytesIO - - def get_binary_stdout(): - return sys.stdout.buffer - - def get_binary_stdin(): - return sys.stdin.buffer - -else: - # Python 2 - Python = 2 - - asbytes = str - asstr = str - - array_tobytes = array.array.tostring - - IntTypes = (int, long) - StrType = basestring - UnicodeType = unicode - - #range_g = xrange # range generator - def range_g(*args): - # we want to use xrange here but on python 2 it does not work with long ints - try: - return xrange(*args) - except OverflowError: - start = 0 - stop = 0 - step = 1 - n = len(args) - if n == 1: - stop = args[0] - elif n == 2: - start, stop = args - elif n == 3: - start, stop, step = args - else: - raise TypeError('wrong number of arguments in range_g call!') - if step == 0: - raise ValueError('step cannot be zero') - if step > 0: - def up(start, stop, step): - while start < stop: - yield start - start += step - return up(start, stop, step) - else: - def down(start, stop, step): - while start > stop: - yield start - start += step - return down(start, stop, step) - - range_l = range # range list - - def dict_keys(dikt): # dict keys list - return dikt.keys() - def dict_keys_g(dikt): # dict keys generator - return dikt.keys() - def dict_items_g(dikt): # dict items generator - return dikt.items() - - from cStringIO import StringIO - BytesIO = StringIO - - import os - def _force_stream_binary(stream): - """Force binary mode for stream on Windows.""" - if os.name == 'nt': - f_fileno = getattr(stream, 'fileno', None) - if f_fileno: - fileno = f_fileno() - if fileno >= 0: - import msvcrt - msvcrt.setmode(fileno, os.O_BINARY) - return stream - - def get_binary_stdout(): - return _force_stream_binary(sys.stdout) - - def get_binary_stdin(): - return _force_stream_binary(sys.stdin) diff --git a/intelhex/getsizeof.py b/intelhex/getsizeof.py deleted file mode 100644 index 105e14a..0000000 --- a/intelhex/getsizeof.py +++ /dev/null @@ -1,64 +0,0 @@ -# Recursive version sys.getsizeof(). Extendable with custom handlers. -# Code from http://code.activestate.com/recipes/577504/ -# Created by Raymond Hettinger on Fri, 17 Dec 2010 (MIT) - -import sys -from itertools import chain -from collections import deque -try: - from reprlib import repr -except ImportError: - pass - -def total_size(o, handlers={}, verbose=False): - """ Returns the approximate memory footprint an object and all of its contents. - - Automatically finds the contents of the following builtin containers and - their subclasses: tuple, list, deque, dict, set and frozenset. - To search other containers, add handlers to iterate over their contents: - - handlers = {SomeContainerClass: iter, - OtherContainerClass: OtherContainerClass.get_elements} - - """ - dict_handler = lambda d: chain.from_iterable(d.items()) - all_handlers = {tuple: iter, - list: iter, - deque: iter, - dict: dict_handler, - set: iter, - frozenset: iter, - } - all_handlers.update(handlers) # user handlers take precedence - seen = set() # track which object id's have already been seen - default_size = sys.getsizeof(0) # estimate sizeof object without __sizeof__ - - def sizeof(o): - if id(o) in seen: # do not double count the same object - return 0 - seen.add(id(o)) - s = sys.getsizeof(o, default_size) - - if verbose: - print(s, type(o), repr(o))#, file=stderr) - - for typ, handler in all_handlers.items(): - if isinstance(o, typ): - s += sum(map(sizeof, handler(o))) - break - return s - - return sizeof(o) - - -##### Example call ##### - -if __name__ == '__main__': - #d = dict(a=1, b=2, c=3, d=[4,5,6,7], e='a string of chars') - print("dict 3 elements") - d = {0:0xFF, 1:0xEE, 2:0xCC} - print(total_size(d, verbose=True)) - - #print("array 3 elements") - #import array - #print(total_size(array.array('B', b'\x01\x02\x03'))) diff --git a/intelhex/scripts/__init__.py b/intelhex/scripts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/intelhex/scripts/bin2hex.py b/intelhex/scripts/bin2hex.py deleted file mode 100755 index 6a2545a..0000000 --- a/intelhex/scripts/bin2hex.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2008-2018 Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -'''Intel HEX file format bin2hex convertor utility.''' - -VERSION = '2.3.0' - -def main(): - import getopt - import os - import sys - - usage = '''Bin2Hex convertor utility. -Usage: - python bin2hex.py [options] INFILE [OUTFILE] - -Arguments: - INFILE name of bin file for processing. - Use '-' for reading from stdin. - - OUTFILE name of output file. If omitted then output - will be writing to stdout. - -Options: - -h, --help this help message. - -v, --version version info. - --offset=N offset for loading bin file (default: 0). -''' - - offset = 0 - - try: - opts, args = getopt.getopt(sys.argv[1:], "hv", - ["help", "version", "offset="]) - - for o, a in opts: - if o in ("-h", "--help"): - print(usage) - sys.exit(0) - elif o in ("-v", "--version"): - print(VERSION) - sys.exit(0) - elif o in ("--offset"): - base = 10 - if a[:2].lower() == '0x': - base = 16 - try: - offset = int(a, base) - except: - raise getopt.GetoptError('Bad offset value') - - if not args: - raise getopt.GetoptError('Input file is not specified') - - if len(args) > 2: - raise getopt.GetoptError('Too many arguments') - - except getopt.GetoptError: - msg = sys.exc_info()[1] # current exception - txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool - print(txt) - print(usage) - sys.exit(2) - - from intelhex import compat - - fin = args[0] - if fin == '-': - # read from stdin - fin = compat.get_binary_stdin() - elif not os.path.isfile(fin): - txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool - print(txt) - sys.exit(1) - - if len(args) == 2: - fout = args[1] - else: - # write to stdout - fout = sys.stdout # compat.get_binary_stdout() - - from intelhex import bin2hex - sys.exit(bin2hex(fin, fout, offset)) - -if __name__ == '__main__': - main() diff --git a/intelhex/scripts/hex2bin.py b/intelhex/scripts/hex2bin.py deleted file mode 100755 index 9533837..0000000 --- a/intelhex/scripts/hex2bin.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2005-2018 Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -'''Intel HEX file format hex2bin convertor utility.''' - -VERSION = '2.3.0' - -def main(): - import getopt - import os - import sys - - usage = '''Hex2Bin convertor utility. -Usage: - python hex2bin.py [options] INFILE [OUTFILE] - -Arguments: - INFILE name of hex file for processing. - OUTFILE name of output file. If omitted then output - will be writing to stdout. - -Options: - -h, --help this help message. - -v, --version version info. - -p, --pad=FF pad byte for empty spaces (ascii hex value). - -r, --range=START:END specify address range for writing output - (ascii hex value). - Range can be in form 'START:' or ':END'. - -l, --length=NNNN, - -s, --size=NNNN size of output (decimal value). -''' - - pad = None - start = None - end = None - size = None - - try: - opts, args = getopt.getopt(sys.argv[1:], "hvp:r:l:s:", - ["help", "version", "pad=", "range=", - "length=", "size="]) - - for o, a in opts: - if o in ("-h", "--help"): - print(usage) - sys.exit(0) - elif o in ("-v", "--version"): - print(VERSION) - sys.exit(0) - elif o in ("-p", "--pad"): - try: - pad = int(a, 16) & 0x0FF - except: - raise getopt.GetoptError('Bad pad value') - elif o in ("-r", "--range"): - try: - l = a.split(":") - if l[0] != '': - start = int(l[0], 16) - if l[1] != '': - end = int(l[1], 16) - except: - raise getopt.GetoptError('Bad range value(s)') - elif o in ("-l", "--lenght", "-s", "--size"): - try: - size = int(a, 10) - except: - raise getopt.GetoptError('Bad size value') - - if start != None and end != None and size != None: - raise getopt.GetoptError('Cannot specify START:END and SIZE simultaneously') - - if not args: - raise getopt.GetoptError('Hex file is not specified') - - if len(args) > 2: - raise getopt.GetoptError('Too many arguments') - - except getopt.GetoptError: - msg = sys.exc_info()[1] # current exception - txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool - print(txt) - print(usage) - sys.exit(2) - - fin = args[0] - if not os.path.isfile(fin): - txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool - print(txt) - sys.exit(1) - - if len(args) == 2: - fout = args[1] - else: - # write to stdout - from intelhex import compat - fout = compat.get_binary_stdout() - - from intelhex import hex2bin - sys.exit(hex2bin(fin, fout, start, end, size, pad)) - -if __name__ == '__main__': - main() diff --git a/intelhex/scripts/hex2dump.py b/intelhex/scripts/hex2dump.py deleted file mode 100755 index 364fe1f..0000000 --- a/intelhex/scripts/hex2dump.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2008-2018 Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -"""Show content of hex file as hexdump.""" - -VERSION = '2.3.0' - -USAGE = '''hex2dump: show content of hex file as hexdump. -Usage: - python hex2dump.py [options] HEXFILE - -Options: - -h, --help this help message. - -v, --version version info. - -r, --range=START:END specify address range for dumping - (ascii hex value). - Range can be in form 'START:' or ':END'. - --width=N dump N data bytes per line (default: 16). - -Arguments: - HEXFILE name of hex file for processing (use '-' to read - from stdin) -''' - -import sys - -DEFAULT_WIDTH = 16 - -def hex2dump(hexfile, start=None, end=None, width=DEFAULT_WIDTH): - import intelhex - if hexfile == '-': - hexfile = sys.stdin - try: - ih = intelhex.IntelHex(hexfile) - except (IOError, intelhex.IntelHexError): - e = sys.exc_info()[1] # current exception - sys.stderr.write('Error reading file: %s\n' % e) - return 1 - if not (start is None and end is None): - ih = ih[slice(start,end)] - ih.dump(tofile=sys.stdout, width=width) - return 0 - - -def main(argv=None): - import getopt - - if argv is None: - argv = sys.argv[1:] - - start = None - end = None - width = DEFAULT_WIDTH - - try: - opts, args = getopt.getopt(sys.argv[1:], "hvp:r:", - ["help", "version", "range=", "width="]) - for o, a in opts: - if o in ("-h", "--help"): - print(USAGE) - return 0 - elif o in ("-v", "--version"): - print(VERSION) - return 0 - elif o in ("-r", "--range"): - try: - l = a.split(":") - if l[0] != '': - start = int(l[0], 16) - if l[1] != '': - end = int(l[1], 16) - except: - raise getopt.GetoptError('Bad range value(s)') - elif o == "--width": - try: - width = int(a) - if width < 1: - raise ValueError - except: - raise getopt.GetoptError('Bad width value (%s)' % a) - if not args: - raise getopt.GetoptError('Hex file is not specified') - if len(args) > 1: - raise getopt.GetoptError('Too many arguments') - except getopt.GetoptError: - msg = sys.exc_info()[1] # current exception - txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool - print(txt) - print(USAGE) - return 2 - - try: - return hex2dump(args[0], start, end, width) - except IOError: - e = sys.exc_info()[1] # current exception - import errno - if e.errno not in (0, errno.EPIPE): - raise - - -if __name__ == '__main__': - import sys - sys.exit(main()) diff --git a/intelhex/scripts/hexdiff.py b/intelhex/scripts/hexdiff.py deleted file mode 100755 index 8acb58b..0000000 --- a/intelhex/scripts/hexdiff.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2011-2018 Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -"""Produce diff for 2 hex files using hex dump as string representation -of compared data. -""" - -VERSION = '2.3.0' - -USAGE = '''hexdiff: diff dumps of 2 hex files. -Usage: - python hexdiff.py [options] FILE1 FILE2 - -Options: - -h, --help this help message. - -v, --version version info. -''' - -import sys - - -def main(argv=None): - import getopt - - if argv is None: - argv = sys.argv[1:] - try: - opts, args = getopt.gnu_getopt(argv, 'hv', ['help', 'version']) - - for o,a in opts: - if o in ('-h', '--help'): - print(USAGE) - return 0 - elif o in ('-v', '--version'): - print(VERSION) - return 0 - - except getopt.GetoptError: - e = sys.exc_info()[1] # current exception - sys.stderr.write(str(e)+"\n") - sys.stderr.write(USAGE+"\n") - return 1 - - if len(args) != 2: - sys.stderr.write("ERROR: You should specify 2 files to diff.\n") - sys.stderr.write(USAGE+"\n") - return 1 - - fname1, fname2 = args - - from intelhex import IntelHex, diff_dumps - ih1 = IntelHex(fname1) - ih2 = IntelHex(fname2) - diff_dumps(ih1, ih2, name1=fname1, name2=fname2) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/intelhex/scripts/hexinfo.py b/intelhex/scripts/hexinfo.py deleted file mode 100755 index e4b6374..0000000 --- a/intelhex/scripts/hexinfo.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2015 Andrew Fernandes -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -"""Summarize the information in a hex file by printing the execution - start address (if any), and the address ranges covered by the - data (if any), in YAML format. -""" - -VERSION = '2.3.0' - -USAGE = '''hexinfo: summarize a hex file's contents. -Usage: - python hexinfo.py [options] FILE [ FILE ... ] - -Options: - -h, --help this help message. - -v, --version version info. -''' - -import sys - -INDENT = ' ' -INLIST = '- ' - -def summarize_yaml(fname): - print("{:s}file: '{:s}'".format(INLIST, fname)) - from intelhex import IntelHex - ih = IntelHex(fname) - if ih.start_addr: - keys = sorted(ih.start_addr.keys()) - if keys == ['CS','IP']: - entry = ih.start_addr['CS'] * 16 + ih.start_addr['IP'] - elif keys == ['EIP']: - entry = ih.start_addr['EIP'] - else: - raise RuntimeError("unknown 'IntelHex.start_addr' found") - print("{:s}entry: 0x{:08X}".format(INDENT, entry)) - segments = ih.segments() - if segments: - print("{:s}data:".format(INDENT)) - for s in segments: - print("{:s}{:s}{{ first: 0x{:08X}, last: 0x{:08X}, length: 0x{:08X} }}".format(INDENT, INLIST, s[0], s[1]-1, s[1]-s[0])) - print("") - -def main(argv=None): - import getopt - - if argv is None: - argv = sys.argv[1:] - try: - opts, args = getopt.gnu_getopt(argv, 'hv', ['help', 'version']) - - for o,a in opts: - if o in ('-h', '--help'): - print(USAGE) - return 0 - elif o in ('-v', '--version'): - print(VERSION) - return 0 - - except getopt.GetoptError: - e = sys.exc_info()[1] # current exception - sys.stderr.write(str(e)+"\n") - sys.stderr.write(USAGE+"\n") - return 1 - - if len(args) < 1: - sys.stderr.write("ERROR: You should specify one or more files to summarize.\n") - sys.stderr.write(USAGE+"\n") - return 1 - - for fname in args: - summarize_yaml(fname) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/intelhex/scripts/hexmerge.py b/intelhex/scripts/hexmerge.py deleted file mode 100755 index 8be98e8..0000000 --- a/intelhex/scripts/hexmerge.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2008-2018 Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -"""Merge content of several hex files into one file.""" - -VERSION = '2.3.0' - -USAGE = '''hexmerge: merge content of hex files. -Usage: - python hexmerge.py [options] FILES... - -Options: - -h, --help this help message. - -v, --version version info. - -o, --output=FILENAME output file name (emit output to stdout - if option is not specified) - -r, --range=START:END specify address range for output - (ascii hex value). Both values are inclusive. - Range can be in form 'START:' or ':END'. - --no-start-addr Don't write start addr to output file. - --overlap=METHOD What to do when data in files overlapped. - Supported variants: - * error -- stop and show error message (default) - * ignore -- keep data from first file that - contains data at overlapped address - * replace -- use data from last file that - contains data at overlapped address - -Arguments: - FILES list of hex files for merging - (use '-' to read content from stdin) - -You can specify address range for each file in the form: - - filename:START:END - -See description of range option above. - -You can omit START or END, so supported variants are: - - filename:START: read filename and use data starting from START addr - filename::END read filename and use data till END addr - -Use entire file content: - - filename -or - filename:: -''' - -import sys - - -def main(args=None): - import getopt - - output = None - start = None - end = None - write_start_addr = True - overlap = 'error' - - if args is None: - args = sys.argv[1:] - try: - opts, args = getopt.gnu_getopt(args, 'hvo:r:', - ['help', 'version', - 'output=', 'range=', - 'no-start-addr', 'overlap=', - ]) - - for o,a in opts: - if o in ('-h', '--help'): - print(USAGE) - return 0 - elif o in ('-v', '--version'): - print(VERSION) - return 0 - elif o in ('-o', '--output'): - output = a - elif o in ("-r", "--range"): - try: - l = a.split(":") - if l[0] != '': - start = int(l[0], 16) - if l[1] != '': - end = int(l[1], 16) - except (ValueError, IndexError): - raise getopt.GetoptError('Bad range value(s)') - elif o == '--no-start-addr': - write_start_addr = False - elif o == '--overlap': - if a in ('error', 'ignore', 'replace'): - overlap = a - else: - raise getopt.GetoptError('Bad overlap value') - - if len(args) == 0: - raise getopt.GetoptError('You should specify file list') - - except getopt.GetoptError: - e = sys.exc_info()[1] # current exception - sys.stderr.write(str(e)+"\n") - sys.stderr.write(USAGE+"\n") - return 1 - - import intelhex - # TODO: move actual merge code into intelhex package as helper function - # and write couple of tests for it. - res = intelhex.IntelHex() - - def end_addr_inclusive(addr): - if addr is not None: - return addr + 1 - return addr - - for f in args: - try: - fname, fstart, fend = intelhex._get_file_and_addr_range(f) - except intelhex._BadFileNotation: - sys.stderr.write('Bad argument: "%s"\n' % f) - sys.stderr.write(USAGE+"\n") - return 1 - if fname == '-': - fname = sys.stdin - ih = intelhex.IntelHex(fname) - if (fstart, fend) != (None, None): - ih = ih[fstart:end_addr_inclusive(fend)] - try: - res.merge(ih, overlap) - except intelhex.AddressOverlapError: - e = sys.exc_info()[1] # current exception - sys.stderr.write('Merging: '+fname+"\n") - sys.stderr.write(str(e)+"\n") - return 1 - - if (start, end) != (None, None): - res = res[start:end_addr_inclusive(end)] - if output is None: - output = sys.stdout - res.write_hex_file(output, write_start_addr) - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/intelhex/test.py b/intelhex/test.py deleted file mode 100755 index 2aff575..0000000 --- a/intelhex/test.py +++ /dev/null @@ -1,1837 +0,0 @@ -# Copyright (c) 2005-2018, Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -"""Test suite for IntelHex library.""" - -import array -import os -import shlex -import subprocess -import sys -import tempfile -import unittest - -import intelhex -from intelhex import ( - IntelHex, - IntelHexError, - HexReaderError, - AddressOverlapError, - HexRecordError, - RecordLengthError, - RecordTypeError, - RecordChecksumError, - EOFRecordError, - ExtendedSegmentAddressRecordError, - ExtendedLinearAddressRecordError, - StartSegmentAddressRecordError, - StartLinearAddressRecordError, - DuplicateStartAddressRecordError, - InvalidStartAddressValueError, - _EndOfFile, - BadAccess16bit, - hex2bin, - Record, - ) -from intelhex import compat -from intelhex.compat import ( - BytesIO, - StringIO, - UnicodeType, - array_tobytes, - asbytes, - asstr, - dict_items_g, - range_g, - range_l, - ) -from intelhex.__version__ import version_str - -__docformat__ = 'restructuredtext' - -## -# Data for tests - -hex8 = '''\ -:1004E300CFF0FBE2FDF220FF20F2E120E2FBE6F396 -:1004F3000A00FDE0E1E2E3B4E4E5BAE6E7B3BFE80E -:10050300E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8E0 -:10051300F9FCFEFF00C0C1C2C3A5C4C5AAC6C7B2C9 -:10052300AFC8C9CACBCCCDCECFD0D1D2D3D4D5D6F8 -:07053300D7D8D9DCDEDF00A0 -:10053A0078227C007D007BFF7A0479F57E007F2398 -:10054A0012042F78457C007D007BFF7A0579187E9E -:10055A00007F2212042F759850438920758DDDD2B1 -:10056A008ED2996390017BFF7A0479E31200658049 -:01057A00FE82 -:030000000205A254 -:0C05A200787FE4F6D8FD75817A02053AF6 -:10035F00E709F608DFFA8046E709F208DFFA803E80 -:10036F0088828C83E709F0A3DFFA8032E309F6086D -:10037F00DFFA8078E309F208DFFA807088828C83D5 -:10038F00E309F0A3DFFA806489828A83E0A3F60889 -:10039F00DFFA805889828A83E0A3F208DFFA804C63 -:1003AF0080D280FA80C680D4806980F2803380103A -:1003BF0080A680EA809A80A880DA80E280CA8033A3 -:1003CF0089828A83ECFAE493A3C8C582C8CCC5831B -:1003DF00CCF0A3C8C582C8CCC583CCDFE9DEE780EB -:1003EF000D89828A83E493A3F608DFF9ECFAA9F06A -:1003FF00EDFB2289828A83ECFAE0A3C8C582C8CCC0 -:10040F00C583CCF0A3C8C582C8CCC583CCDFEADED8 -:10041F00E880DB89828A83E493A3F208DFF980CC3A -:10042F0088F0EF60010E4E60C388F0ED2402B40433 -:10043F000050B9F582EB2402B4040050AF232345DA -:06044F0082239003AF734D -:10000300E576246AF8E60576227867300702786A8F -:10001300E475F0011204AD0204552000EB7F2ED2EB -:10002300008018EF540F2490D43440D4FF30040BD5 -:10003300EF24BFB41A0050032461FFE57760021573 -:1000430077057AE57A7002057930070D7867E475EC -:10005300F0011204ADEF02049B02057B7403D20787 -:100063008003E4C207F5768B678A688969E4F577CC -:10007300F579F57AE57760077F2012003E80F57504 -:1000830078FFC201C200C202C203C205C206C2088F -:1000930012000CFF700D3007057F0012004FAF7A7E -:1000A300AE7922B4255FC2D5C20412000CFF24D05E -:1000B300B40A00501A75F00A787730D50508B6FFF0 -:1000C3000106C6A426F620D5047002D20380D924E3 -:1000D300CFB41A00EF5004C2E5D20402024FD2019A -:1000E30080C6D20080C0D20280BCD2D580BAD205ED -:1000F30080B47F2012003E2002077401B5770040D0 -:10010300F1120003FF12003E020077D208D20680EC -:1001130095120003FB120003FA120003F94A4B7015 -:100123000679207A037BFF20022EE577602A7E0082 -:100133008E8275830012046E60060EEE657870F091 -:10014300C2D5EBC0E0EAC0E0E9C0E0EE120296D00F -:10015300E0F9D0E0FAD0E0FB120455FF60AAEBC04F -:10016300E0EAC0E0E9C0E012003ED0E02401F9D0AB -:10017300E03400FAD0E0FBE5780460DCD578D98080 -:10018300877BFF7A027992D202809C791080027970 -:1001930008C206C2088008D2D5790A8004790AC247 -:1001A300D5E578047002F578E4FAFDFEFF1200034A -:1001B300FC7B08200113120003FD7B1030000A12A0 -:1001C3000003FE120003FF7B20EC3382D592D5504F -:1001D30013C3E43000069FFFE49EFEE42001039D69 -:1001E300FDE49CFCE4CBF8C201EC700CCFCECDCC8B -:1001F300E824F8F870F38017C3EF33FFEE33FEED16 -:1002030033FDEC33FCEB33FB994002FB0FD8E9EBF6 -:10021300300105F8D0E0C448B201C0E00AEC4D4E0D -:100223004F78207B0070C2EAB5780040BCC0E01272 -:100233000298D0F0D0E0200104C4C0E0C4B201C0F1 -:10024300F0120027D0F0D5F0EB0200771204BD01C5 -:100253001453018E5800E54C00E14201924F019A7C -:0F02630044019A4900FA4301A0550184460184E1 -:100272004501844703405000E92D00ED2E01102B6B -:1002820000F123010E2003292A00A94800000108D9 -:100292003F3F3F00790AA2D5200314300509B91067 -:1002A200020404B9080104A2D52006025001042068 -:1002B20002689202B577005034C0E07F2030031903 -:1002C2007F30A20272067205500F1202EFC202C202 -:1002D20006C205C2087F30800F300503E9C0E01274 -:1002E200003E300503D0E0F9D0E0B577CC300517F9 -:1002F2007F30B9100C12003E7F583004077F78809F -:1003020003B9080312003E3002057F2D02003E7F32 -:10031200202008F87F2B2006F322920280CF286E3D -:10032200756C6C2900D2011200033001F8C2017809 -:100332007730D50108F60200A92D50434958120022 -:10034200032403B405004001E490033B9312002F01 -:0D035200743A12002FD20375770402018E59 -:10045500BB010689828A83E0225002E722BBFE02A5 -:09046500E32289828A83E49322D8 -:10046E00BB010CE58229F582E5833AF583E0225043 -:10047E0006E92582F8E622BBFE06E92582F8E2228D -:0D048E00E58229F582E5833AF583E49322A7 -:10049B00BB010689828A83F0225002F722BBFE0140 -:0204AB00F3223A -:1004AD00FAE6FB0808E6F925F0F618E6CA3AF62250 -:1004BD00D083D082F8E4937012740193700DA3A3CE -:1004CD0093F8740193F5828883E4737402936860E2 -:0604DD00EFA3A3A380DFE2 -:10057B00EFB40A07740D120586740A309811A89906 -:10058B00B8130CC2983098FDA899C298B811F630E0 -:07059B0099FDC299F59922B8 -:00000001FF -''' -bin8 = array.array('B',[2, 5, 162, 229, 118, 36, 106, 248, 230, 5, 118, 34, - 120, 103, 48, 7, 2, 120, 106, 228, 117, 240, 1, 18, - 4, 173, 2, 4, 85, 32, 0, 235, 127, 46, 210, 0, 128, - 24, 239, 84, 15, 36, 144, 212, 52, 64, 212, 255, 48, - 4, 11, 239, 36, 191, 180, 26, 0, 80, 3, 36, 97, 255, - 229, 119, 96, 2, 21, 119, 5, 122, 229, 122, 112, 2, - 5, 121, 48, 7, 13, 120, 103, 228, 117, 240, 1, 18, - 4, 173, 239, 2, 4, 155, 2, 5, 123, 116, 3, 210, 7, - 128, 3, 228, 194, 7, 245, 118, 139, 103, 138, 104, - 137, 105, 228, 245, 119, 245, 121, 245, 122, 229, - 119, 96, 7, 127, 32, 18, 0, 62, 128, 245, 117, 120, - 255, 194, 1, 194, 0, 194, 2, 194, 3, 194, 5, 194, 6, - 194, 8, 18, 0, 12, 255, 112, 13, 48, 7, 5, 127, 0, - 18, 0, 79, 175, 122, 174, 121, 34, 180, 37, 95, 194, - 213, 194, 4, 18, 0, 12, 255, 36, 208, 180, 10, 0, 80, - 26, 117, 240, 10, 120, 119, 48, 213, 5, 8, 182, 255, - 1, 6, 198, 164, 38, 246, 32, 213, 4, 112, 2, 210, 3, - 128, 217, 36, 207, 180, 26, 0, 239, 80, 4, 194, 229, - 210, 4, 2, 2, 79, 210, 1, 128, 198, 210, 0, 128, 192, - 210, 2, 128, 188, 210, 213, 128, 186, 210, 5, 128, - 180, 127, 32, 18, 0, 62, 32, 2, 7, 116, 1, 181, 119, - 0, 64, 241, 18, 0, 3, 255, 18, 0, 62, 2, 0, 119, 210, - 8, 210, 6, 128, 149, 18, 0, 3, 251, 18, 0, 3, 250, - 18, 0, 3, 249, 74, 75, 112, 6, 121, 32, 122, 3, 123, - 255, 32, 2, 46, 229, 119, 96, 42, 126, 0, 142, 130, - 117, 131, 0, 18, 4, 110, 96, 6, 14, 238, 101, 120, - 112, 240, 194, 213, 235, 192, 224, 234, 192, 224, - 233, 192, 224, 238, 18, 2, 150, 208, 224, 249, 208, - 224, 250, 208, 224, 251, 18, 4, 85, 255, 96, 170, - 235, 192, 224, 234, 192, 224, 233, 192, 224, 18, 0, - 62, 208, 224, 36, 1, 249, 208, 224, 52, 0, 250, 208, - 224, 251, 229, 120, 4, 96, 220, 213, 120, 217, 128, - 135, 123, 255, 122, 2, 121, 146, 210, 2, 128, 156, - 121, 16, 128, 2, 121, 8, 194, 6, 194, 8, 128, 8, 210, - 213, 121, 10, 128, 4, 121, 10, 194, 213, 229, 120, 4, - 112, 2, 245, 120, 228, 250, 253, 254, 255, 18, 0, 3, - 252, 123, 8, 32, 1, 19, 18, 0, 3, 253, 123, 16, 48, - 0, 10, 18, 0, 3, 254, 18, 0, 3, 255, 123, 32, 236, - 51, 130, 213, 146, 213, 80, 19, 195, 228, 48, 0, 6, - 159, 255, 228, 158, 254, 228, 32, 1, 3, 157, 253, - 228, 156, 252, 228, 203, 248, 194, 1, 236, 112, 12, - 207, 206, 205, 204, 232, 36, 248, 248, 112, 243, 128, - 23, 195, 239, 51, 255, 238, 51, 254, 237, 51, 253, - 236, 51, 252, 235, 51, 251, 153, 64, 2, 251, 15, 216, - 233, 235, 48, 1, 5, 248, 208, 224, 196, 72, 178, 1, - 192, 224, 10, 236, 77, 78, 79, 120, 32, 123, 0, 112, - 194, 234, 181, 120, 0, 64, 188, 192, 224, 18, 2, 152, - 208, 240, 208, 224, 32, 1, 4, 196, 192, 224, 196, - 178, 1, 192, 240, 18, 0, 39, 208, 240, 213, 240, 235, - 2, 0, 119, 18, 4, 189, 1, 20, 83, 1, 142, 88, 0, 229, - 76, 0, 225, 66, 1, 146, 79, 1, 154, 68, 1, 154, 73, - 0, 250, 67, 1, 160, 85, 1, 132, 70, 1, 132, 69, 1, - 132, 71, 3, 64, 80, 0, 233, 45, 0, 237, 46, 1, 16, - 43, 0, 241, 35, 1, 14, 32, 3, 41, 42, 0, 169, 72, 0, - 0, 1, 8, 63, 63, 63, 0, 121, 10, 162, 213, 32, 3, 20, - 48, 5, 9, 185, 16, 2, 4, 4, 185, 8, 1, 4, 162, 213, - 32, 6, 2, 80, 1, 4, 32, 2, 104, 146, 2, 181, 119, 0, - 80, 52, 192, 224, 127, 32, 48, 3, 25, 127, 48, 162, - 2, 114, 6, 114, 5, 80, 15, 18, 2, 239, 194, 2, 194, - 6, 194, 5, 194, 8, 127, 48, 128, 15, 48, 5, 3, 233, - 192, 224, 18, 0, 62, 48, 5, 3, 208, 224, 249, 208, - 224, 181, 119, 204, 48, 5, 23, 127, 48, 185, 16, 12, - 18, 0, 62, 127, 88, 48, 4, 7, 127, 120, 128, 3, 185, - 8, 3, 18, 0, 62, 48, 2, 5, 127, 45, 2, 0, 62, 127, - 32, 32, 8, 248, 127, 43, 32, 6, 243, 34, 146, 2, 128, - 207, 40, 110, 117, 108, 108, 41, 0, 210, 1, 18, 0, 3, - 48, 1, 248, 194, 1, 120, 119, 48, 213, 1, 8, 246, 2, - 0, 169, 45, 80, 67, 73, 88, 18, 0, 3, 36, 3, 180, 5, - 0, 64, 1, 228, 144, 3, 59, 147, 18, 0, 47, 116, 58, - 18, 0, 47, 210, 3, 117, 119, 4, 2, 1, 142, 231, 9, - 246, 8, 223, 250, 128, 70, 231, 9, 242, 8, 223, 250, - 128, 62, 136, 130, 140, 131, 231, 9, 240, 163, 223, - 250, 128, 50, 227, 9, 246, 8, 223, 250, 128, 120, - 227, 9, 242, 8, 223, 250, 128, 112, 136, 130, 140, - 131, 227, 9, 240, 163, 223, 250, 128, 100, 137, - 130, 138, 131, 224, 163, 246, 8, 223, 250, 128, 88, - 137, 130, 138, 131, 224, 163, 242, 8, 223, 250, 128, - 76, 128, 210, 128, 250, 128, 198, 128, 212, 128, 105, - 128, 242, 128, 51, 128, 16, 128, 166, 128, 234, 128, - 154, 128, 168, 128, 218, 128, 226, 128, 202, 128, 51, - 137, 130, 138, 131, 236, 250, 228, 147, 163, 200, - 197, 130, 200, 204, 197, 131, 204, 240, 163, 200, - 197, 130, 200, 204, 197, 131, 204, 223, 233, 222, - 231, 128, 13, 137, 130, 138, 131, 228, 147, 163, 246, - 8, 223, 249, 236, 250, 169, 240, 237, 251, 34, 137, - 130, 138, 131, 236, 250, 224, 163, 200, 197, 130, - 200, 204, 197, 131, 204, 240, 163, 200, 197, 130, - 200, 204, 197, 131, 204, 223, 234, 222, 232, 128, - 219, 137, 130, 138, 131, 228, 147, 163, 242, 8, - 223, 249, 128, 204, 136, 240, 239, 96, 1, 14, 78, - 96, 195, 136, 240, 237, 36, 2, 180, 4, 0, 80, 185, - 245, 130, 235, 36, 2, 180, 4, 0, 80, 175, 35, 35, - 69, 130, 35, 144, 3, 175, 115, 187, 1, 6, 137, 130, - 138, 131, 224, 34, 80, 2, 231, 34, 187, 254, 2, 227, - 34, 137, 130, 138, 131, 228, 147, 34, 187, 1, 12, - 229, 130, 41, 245, 130, 229, 131, 58, 245, 131, 224, - 34, 80, 6, 233, 37, 130, 248, 230, 34, 187, 254, 6, - 233, 37, 130, 248, 226, 34, 229, 130, 41, 245, 130, - 229, 131, 58, 245, 131, 228, 147, 34, 187, 1, 6, - 137, 130, 138, 131, 240, 34, 80, 2, 247, 34, 187, - 254, 1, 243, 34, 250, 230, 251, 8, 8, 230, 249, 37, - 240, 246, 24, 230, 202, 58, 246, 34, 208, 131, 208, - 130, 248, 228, 147, 112, 18, 116, 1, 147, 112, 13, - 163, 163, 147, 248, 116, 1, 147, 245, 130, 136, - 131, 228, 115, 116, 2, 147, 104, 96, 239, 163, 163, - 163, 128, 223, 207, 240, 251, 226, 253, 242, 32, - 255, 32, 242, 225, 32, 226, 251, 230, 243, 10, 0, - 253, 224, 225, 226, 227, 180, 228, 229, 186, 230, - 231, 179, 191, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 252, 254, 255, 0, 192, 193, 194, 195, 165, 196, - 197, 170, 198, 199, 178, 175, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 220, 222, 223, 0, 120, 34, 124, - 0, 125, 0, 123, 255, 122, 4, 121, 245, 126, 0, 127, - 35, 18, 4, 47, 120, 69, 124, 0, 125, 0, 123, 255, - 122, 5, 121, 24, 126, 0, 127, 34, 18, 4, 47, 117, - 152, 80, 67, 137, 32, 117, 141, 221, 210, 142, 210, - 153, 99, 144, 1, 123, 255, 122, 4, 121, 227, 18, 0, - 101, 128, 254, 239, 180, 10, 7, 116, 13, 18, 5, 134, - 116, 10, 48, 152, 17, 168, 153, 184, 19, 12, 194, - 152, 48, 152, 253, 168, 153, 194, 152, 184, 17, - 246, 48, 153, 253, 194, 153, 245, 153, 34, 120, 127, - 228, 246, 216, 253, 117, 129, 122, 2, 5, 58]) - - -hex16 = """:020000040000FA -:10000000000083120313072055301820042883169C -:10001000031340309900181598168312031318160D -:1000200098170800831203138C1E14281A0808005E -:0C003000831203130C1E1A28990008000C -:00000001FF -""" -bin16 = array.array('H', [0x0000, 0x1283, 0x1303, 0x2007, - 0x3055, 0x2018, 0x2804, 0x1683, - 0x1303, 0x3040, 0x0099, 0x1518, - 0x1698, 0x1283, 0x1303, 0x1618, - 0x1798, 0x0008, 0x1283, 0x1303, - 0x1E8C, 0x2814, 0x081A, 0x0008, - 0x1283, 0x1303, 0x1E0C, 0x281A, - 0x0099, 0x0008, 0x3FFF, 0x3FFF]) - - -hex64k = """:020000040000FA -:0100000001FE -:020000040001F9 -:0100000002FD -:00000001FF -""" -data64k = {0: 1, 0x10000: 2} - - -hex_rectype3 = """:0400000312345678E5 -:0100000001FE -:00000001FF -""" -data_rectype3 = {0: 1} -start_addr_rectype3 = {'CS': 0x1234, 'IP': 0x5678} - - -hex_rectype5 = """:0400000512345678E3 -:0100000002FD -:00000001FF -""" -data_rectype5 = {0: 2} -start_addr_rectype5 = {'EIP': 0x12345678} - -hex_empty_file = ':00000001FF\n' - -hex_simple = """\ -:10000000000083120313072055301820042883169C -:10001000031340309900181598168312031318160D -:1000200098170800831203138C1E14281A0808005E -:0C003000831203130C1E1A28990008000C -:00000001FF -""" - -hex_bug_lp_341051 = """\ -:020FEC00E4E738 -:040FF00022E122E1F7 -:00000001FF -""" - - -## -# Test cases - -class TestIntelHexBase(unittest.TestCase): - """Base class for all tests. - Provide additional functionality for testing. - """ - - def assertRaisesMsg(self, excClass, msg, callableObj, *args, **kwargs): - """Just like unittest.TestCase.assertRaises, - but checks that the message is right too. - - Borrowed from Ned Batchelder Blog. - See: http://www.nedbatchelder.com/blog/200609.html#e20060905T064418 - - Typical usage:: - - self.assertRaisesMsg(MyException, "Exception message", - my_function, (arg1, arg2)) - """ - try: - callableObj(*args, **kwargs) - except excClass: - exc = sys.exc_info()[1] # current exception - excMsg = str(exc) - if not msg: - # No message provided: any message is fine. - return - elif excMsg == msg: - # Message provided, and we got the right message: it passes. - return - else: - # Message provided, and it didn't match: fail! - raise self.failureException( - "Right exception, wrong message: got '%s' expected '%s'" % - (excMsg, msg) - ) - else: - if hasattr(excClass, '__name__'): - excName = excClass.__name__ - else: - excName = str(excClass) - raise self.failureException( - "Expected to raise %s, didn't get an exception at all" % - excName - ) - - def assertEqualWrittenData(self, a, b): - return self.assertEqual(a, b, """Written data is incorrect -Should be: -%s - -Written: -%s -""" % (a, b)) -#/class TestIntelHexBase - - -class TestIntelHex(TestIntelHexBase): - - def setUp(self): - self.f = StringIO(hex8) - - def tearDown(self): - self.f.close() - del self.f - - def test_init_from_file(self): - ih = IntelHex(self.f) - for addr in range_g(len(bin8)): - expected = bin8[addr] - actual = ih[addr] - self.assertEqual(expected, actual, - "Data different at address " - "%x (%x != %x)" % (addr, expected, actual)) - - def test_hex_fromfile(self): - ih = IntelHex() - ih.fromfile(self.f, format='hex') - for addr in range_g(len(bin8)): - expected = bin8[addr] - actual = ih[addr] - self.assertEqual(expected, actual, - "Data different at address " - "%x (%x != %x)" % (addr, expected, actual)) - - def test_unicode_filename(self): - handle, fname = tempfile.mkstemp(UnicodeType('')) - os.close(handle) - try: - self.assertTrue(isinstance(fname, UnicodeType)) - f = open(fname, 'w') - try: - f.write(hex8) - finally: - f.close() - ih = IntelHex(fname) - self.assertEqual(0, ih.minaddr()) - self.assertEqual(len(bin8)-1, ih.maxaddr()) - finally: - os.remove(fname) - - def test_tobinarray_empty(self): - ih = IntelHex() - ih.padding = 0xFF # set-up explicit padding value and don't use pad parameter - self.assertEqual(array.array('B', []), ih.tobinarray()) - self.assertEqual(array.array('B', []), ih.tobinarray(start=0)) - self.assertEqual(array.array('B', []), ih.tobinarray(end=2)) - self.assertEqual(array.array('B', [255,255,255]), ih.tobinarray(0,2)) - - def test_tobinarray_with_size(self): - ih = IntelHex(self.f) - self.assertEqual(array.array('B', [2, 5, 162, 229, 118, 36, 106, 248]), - ih.tobinarray(size=8)) # from addr 0 - self.assertEqual(array.array('B', [120, 103, 48, 7, 2, 120, 106, 228]), - ih.tobinarray(start=12, size=8)) - self.assertEqual(array.array('B', [2, 5, 162, 229, 118, 36, 106, 248]), - ih.tobinarray(end=7, size=8)) # addr: 0..7, 8 bytes - self.assertEqual(array.array('B', [120, 103, 48, 7, 2, 120, 106, 228]), - ih.tobinarray(end=19, size=8)) # addr: 12..19, 8 bytes - self.assertRaises(ValueError, ih.tobinarray, start=0, end=7, size=8) - self.assertRaises(ValueError, ih.tobinarray, end=3, size=8) - self.assertRaises(ValueError, ih.tobinarray, size=0) - self.assertRaises(ValueError, ih.tobinarray, size=-1) - - def test_tobinstr(self): - ih = IntelHex(self.f) - s1 = ih.tobinstr() - s2 = array_tobytes(bin8) - self.assertEqual(s2, s1, "data not equal\n%s\n\n%s" % (s1, s2)) - - def test_tobinfile(self): - ih = IntelHex(self.f) - sio = BytesIO() - ih.tobinfile(sio) - s1 = sio.getvalue() - sio.close() - s2 = array_tobytes(bin8) - self.assertEqual(s2, s1, "data not equal\n%s\n\n%s" % (s1, s2)) - # new API: .tofile universal method - sio = BytesIO() - ih.tofile(sio, format='bin') - s1 = sio.getvalue() - sio.close() - s2 = array_tobytes(bin8) - self.assertEqual(s2, s1, "data not equal\n%s\n\n%s" % (s1, s2)) - - def test_tobinfile_realfile(self): - ih = IntelHex(self.f) - tf = tempfile.TemporaryFile(mode='wb') - try: - ih.tobinfile(tf) - finally: - tf.close() - - def test__get_eol_textfile(self): - self.assertEqual('\n', IntelHex._get_eol_textfile('native', 'win32')) - self.assertEqual('\n', IntelHex._get_eol_textfile('native', 'linux')) - self.assertEqual('\n', IntelHex._get_eol_textfile('CRLF', 'win32')) - self.assertEqual('\r\n', IntelHex._get_eol_textfile('CRLF', 'linux')) - self.assertRaisesMsg(ValueError, "wrong eolstyle 'LF'", - IntelHex._get_eol_textfile, 'LF', 'win32') - - def test_write_empty_hexfile(self): - ih = intelhex.IntelHex() - sio = StringIO() - ih.write_hex_file(sio) - s = sio.getvalue() - sio.close() - self.assertEqualWrittenData(hex_empty_file, s) - - def test_write_hexfile(self): - ih = intelhex.IntelHex(StringIO(hex_simple)) - sio = StringIO() - ih.write_hex_file(sio) - s = sio.getvalue() - sio.close() - self.assertEqualWrittenData(hex_simple, s) - # new API: .tofile universal method - sio = StringIO() - ih.tofile(sio, format='hex') - s = sio.getvalue() - sio.close() - self.assertEqualWrittenData(hex_simple, s) - - def test_write_hex_bug_341051(self): - ih = intelhex.IntelHex(StringIO(hex_bug_lp_341051)) - sio = StringIO() - ih.tofile(sio, format='hex') - s = sio.getvalue() - sio.close() - self.assertEqualWrittenData(hex_bug_lp_341051, s) - - def test_write_hex_first_extended_linear_address(self): - ih = IntelHex({0x20000: 0x01}) - sio = StringIO() - ih.write_hex_file(sio) - s = sio.getvalue() - sio.close() - # should be - r = [Record.extended_linear_address(2), - Record.data(0x0000, [0x01]), - Record.eof()] - h = '\n'.join(r) + '\n' - # compare - self.assertEqual(h, s) - - def test_tofile_wrong_format(self): - ih = IntelHex() - sio = StringIO() - self.assertRaises(ValueError, ih.tofile, sio, {'format': 'bad'}) - - def test_todict(self): - ih = IntelHex() - self.assertEqual({}, ih.todict()) - ih = IntelHex(StringIO(hex64k)) - self.assertEqual(data64k, ih.todict()) - ih = IntelHex() - ih[1] = 2 - ih.start_addr = {'EIP': 1234} - self.assertEqual({1: 2, 'start_addr': {'EIP': 1234}}, ih.todict()) - - def test_fromdict(self): - ih = IntelHex() - ih.fromdict({1:2, 3:4}) - self.assertEqual({1:2, 3:4}, ih.todict()) - ih.fromdict({1:5, 6:7}) - self.assertEqual({1:5, 3:4, 6:7}, ih.todict()) - ih = IntelHex() - ih.fromdict({1: 2, 'start_addr': {'EIP': 1234}}) - self.assertEqual({1: 2, 'start_addr': {'EIP': 1234}}, ih.todict()) - # bad dict - self.assertRaises(ValueError, ih.fromdict, {'EIP': 1234}) - self.assertRaises(ValueError, ih.fromdict, {-1: 1234}) - - def test_init_from_obj(self): - ih = IntelHex({1:2, 3:4}) - self.assertEqual({1:2, 3:4}, ih.todict()) - ih.start_addr = {'EIP': 1234} - ih2 = IntelHex(ih) - ih[1] = 5 - ih.start_addr = {'EIP': 5678} - self.assertEqual({1:2, 3:4, 'start_addr': {'EIP': 1234}}, ih2.todict()) - self.assertNotEqual(id(ih), id(ih2)) - - def test_dict_interface(self): - # https://github.com/python-intelhex/intelhex/issues/54 - # uninitialized objects no longer return padding bytes for random - # addresses. Anything set defines an upper address, remaining bytes - # down to zero _will_ yield padding bytes then. - ih = IntelHex() - ih[1] = 0 - self.assertEqual(0xFF, ih[0]) # padding byte substitution - ih[0] = 1 - self.assertEqual(1, ih[0]) - del ih[0] - del ih[1] - self.assertEqual({}, ih.todict()) # padding byte substitution - - def test_len(self): - ih = IntelHex() - self.assertEqual(0, len(ih)) - ih[2] = 1 - self.assertEqual(1, len(ih)) - ih[1000] = 2 - self.assertEqual(2, len(ih)) - - def test_list(self): - # https://github.com/python-intelhex/intelhex/issues/54 - ih = IntelHex() - self.assertEqual([], list(ih)) - ih[2] = 1 - self.assertEqual([0xFF, 0xFF, 1], list(ih)) - - def test__contains__(self): - # https://github.com/python-intelhex/intelhex/issues/TBD - ih = IntelHex() - self.assertFalse(0 in ih) - ih[1] = 0xFF - self.assertTrue(1 in ih) - # big address - ih[2**32-1] = 1 - self.assertTrue((2**32-1) in ih) - # Invalid address - def contains(index): - return index in ih - self.assertRaisesMsg(TypeError, - 'Address should be >= 0.', - contains, -1) - - def test__getitem__(self): - ih = IntelHex() - # https://github.com/python-intelhex/intelhex/issues/54 - # uninitialized objects no longer return padding bytes for random - # addresses. Anything set defines an upper address, remaining bytes - # down to zero _will_ yield padding bytes then. - # simple cases - ih[1] = 0xFF - self.assertEqual(0xFF, ih[0]) - ih[0] = 1 - self.assertEqual(1, ih[0]) - # big address - ih[2**32-1] = 1 - self.assertEqual(0xFF, ih[2**32-2]) - # wrong addr type/value for indexing operations - def getitem(index): - return ih[index] - self.assertRaisesMsg(TypeError, - 'Address should be >= 0.', - getitem, -1) - self.assertRaisesMsg(TypeError, - "Address has unsupported type: %s" % type('foo'), - getitem, 'foo') - # new object with some data - ih = IntelHex() - ih[0] = 1 - ih[1] = 2 - ih[2] = 3 - ih[10] = 4 - # full copy via slicing - ih2 = ih[:] - self.assertTrue(isinstance(ih2, IntelHex)) - self.assertEqual({0:1, 1:2, 2:3, 10:4}, ih2.todict()) - # other slice operations - self.assertEqual({}, ih[3:8].todict()) - self.assertEqual({0:1, 1:2}, ih[0:2].todict()) - self.assertEqual({0:1, 1:2}, ih[:2].todict()) - self.assertEqual({2:3, 10:4}, ih[2:].todict()) - self.assertEqual({0:1, 2:3, 10:4}, ih[::2].todict()) - self.assertEqual({10:4}, ih[3:11].todict()) - # https://github.com/python-intelhex/intelhex/issues/52 - self.assertEqual({}, ih[0:0].todict()) - self.assertEqual({}, ih[1:1].todict()) - - def test__setitem__(self): - ih = IntelHex() - # simple indexing operation - ih[0] = 1 - self.assertEqual({0:1}, ih.todict()) - # errors - def setitem(a,b): - ih[a] = b - self.assertRaisesMsg(TypeError, - 'Address should be >= 0.', - setitem, -1, 0) - self.assertRaisesMsg(TypeError, - "Address has unsupported type: %s" % type('foo'), - setitem, 'foo', 0) - # slice operations - ih[0:4] = range_l(4) - self.assertEqual({0:0, 1:1, 2:2, 3:3}, ih.todict()) - ih[0:] = range_l(5,9) - self.assertEqual({0:5, 1:6, 2:7, 3:8}, ih.todict()) - ih[:4] = range_l(9,13) - self.assertEqual({0:9, 1:10, 2:11, 3:12}, ih.todict()) - # with step - ih = IntelHex() - ih[0:8:2] = range_l(4) - self.assertEqual({0:0, 2:1, 4:2, 6:3}, ih.todict()) - # errors in slice operations - # ih[1:2] = 'a' - self.assertRaisesMsg(ValueError, - 'Slice operation expects sequence of bytes', - setitem, slice(1,2,None), 'a') - # ih[0:1] = [1,2,3] - self.assertRaisesMsg(ValueError, - 'Length of bytes sequence does not match address range', - setitem, slice(0,1,None), [1,2,3]) - # ih[:] = [1,2,3] - self.assertRaisesMsg(TypeError, - 'Unsupported address range', - setitem, slice(None,None,None), [1,2,3]) - # ih[:2] = [1,2,3] - self.assertRaisesMsg(TypeError, - 'start address cannot be negative', - setitem, slice(None,2,None), [1,2,3]) - # ih[0:-3:-1] = [1,2,3] - self.assertRaisesMsg(TypeError, - 'stop address cannot be negative', - setitem, slice(0,-3,-1), [1,2,3]) - - def test__delitem__(self): - ih = IntelHex() - ih[0] = 1 - del ih[0] - self.assertEqual({}, ih.todict()) - # errors - def delitem(addr): - del ih[addr] - self.assertRaises(KeyError, delitem, 1) - self.assertRaisesMsg(TypeError, - 'Address should be >= 0.', - delitem, -1) - self.assertRaisesMsg(TypeError, - "Address has unsupported type: %s" % type('foo'), - delitem, 'foo') - # deleting slice - del ih[0:1] # no error here because of slicing - # - def ihex(size=8): - ih = IntelHex() - for i in range_g(size): - ih[i] = i - return ih - ih = ihex(8) - del ih[:] # delete all data - self.assertEqual({}, ih.todict()) - ih = ihex(8) - del ih[2:6] - self.assertEqual({0:0, 1:1, 6:6, 7:7}, ih.todict()) - ih = ihex(8) - del ih[::2] - self.assertEqual({1:1, 3:3, 5:5, 7:7}, ih.todict()) - - def test_addresses(self): - # empty object - ih = IntelHex() - self.assertEqual([], ih.addresses()) - self.assertEqual(None, ih.minaddr()) - self.assertEqual(None, ih.maxaddr()) - # normal object - ih = IntelHex({1:2, 7:8, 10:0}) - self.assertEqual([1,7,10], ih.addresses()) - self.assertEqual(1, ih.minaddr()) - self.assertEqual(10, ih.maxaddr()) - - def test__get_start_end(self): - # test for private method _get_start_end - # for empty object - ih = IntelHex() - self.assertRaises(intelhex.EmptyIntelHexError, ih._get_start_end) - self.assertRaises(intelhex.EmptyIntelHexError, ih._get_start_end, size=10) - self.assertEqual((0,9), ih._get_start_end(start=0, size=10)) - self.assertEqual((1,10), ih._get_start_end(end=10, size=10)) - # normal object - ih = IntelHex({1:2, 7:8, 10:0}) - self.assertEqual((1,10), ih._get_start_end()) - self.assertEqual((1,10), ih._get_start_end(size=10)) - self.assertEqual((0,9), ih._get_start_end(start=0, size=10)) - self.assertEqual((1,10), ih._get_start_end(end=10, size=10)) - - def test_segments(self): - # test that address segments are correctly summarized - ih = IntelHex() - sg = ih.segments() - self.assertTrue(isinstance(sg, list)) - self.assertEqual(len(sg), 0) - ih[0x100] = 0 - sg = ih.segments() - self.assertTrue(isinstance(sg, list)) - self.assertEqual(len(sg), 1) - self.assertTrue(isinstance(sg[0], tuple)) - self.assertTrue(len(sg[0]) == 2) - self.assertTrue(sg[0][0] < sg[0][1]) - self.assertEqual(min(sg[0]), 0x100) - self.assertEqual(max(sg[0]), 0x101) - ih[0x101] = 1 - sg = ih.segments() - self.assertTrue(isinstance(sg, list)) - self.assertEqual(len(sg), 1) - self.assertTrue(isinstance(sg[0], tuple)) - self.assertTrue(len(sg[0]) == 2) - self.assertTrue(sg[0][0] < sg[0][1]) - self.assertEqual(min(sg[0]), 0x100) - self.assertEqual(max(sg[0]), 0x102) - ih[0x200] = 2 - ih[0x201] = 3 - ih[0x202] = 4 - sg = ih.segments() - self.assertTrue(isinstance(sg, list)) - self.assertEqual(len(sg), 2) - self.assertTrue(isinstance(sg[0], tuple)) - self.assertTrue(len(sg[0]) == 2) - self.assertTrue(sg[0][0] < sg[0][1]) - self.assertTrue(isinstance(sg[1], tuple)) - self.assertTrue(len(sg[1]) == 2) - self.assertTrue(sg[1][0] < sg[1][1]) - self.assertEqual(min(sg[0]), 0x100) - self.assertEqual(max(sg[0]), 0x102) - self.assertEqual(min(sg[1]), 0x200) - self.assertEqual(max(sg[1]), 0x203) - ih[0x204] = 5 - sg = ih.segments() - self.assertEqual(len(sg), 3) - sg = ih.segments(min_gap=2) - self.assertEqual(len(sg), 2) - self.assertEqual(min(sg[1]), 0x200) - self.assertEqual(max(sg[1]), 0x205) - pass - -class TestIntelHexLoadBin(TestIntelHexBase): - - def setUp(self): - self.bytes = asbytes('0123456789') - self.f = BytesIO(self.bytes) - - def tearDown(self): - self.f.close() - - def test_loadbin(self): - ih = IntelHex() - ih.loadbin(self.f) - self.assertEqual(0, ih.minaddr()) - self.assertEqual(9, ih.maxaddr()) - self.assertEqual(self.bytes, ih.tobinstr()) - - def test_bin_fromfile(self): - ih = IntelHex() - ih.fromfile(self.f, format='bin') - self.assertEqual(0, ih.minaddr()) - self.assertEqual(9, ih.maxaddr()) - self.assertEqual(self.bytes, ih.tobinstr()) - - def test_loadbin_w_offset(self): - ih = IntelHex() - ih.loadbin(self.f, offset=100) - self.assertEqual(100, ih.minaddr()) - self.assertEqual(109, ih.maxaddr()) - self.assertEqual(self.bytes, ih.tobinstr()) - - def test_loadfile_format_bin(self): - ih = IntelHex() - ih.loadfile(self.f, format='bin') - self.assertEqual(0, ih.minaddr()) - self.assertEqual(9, ih.maxaddr()) - self.assertEqual(self.bytes, ih.tobinstr()) - - -class TestIntelHexStartingAddressRecords(TestIntelHexBase): - - def _test_read(self, hexstr, data, start_addr): - sio = StringIO(hexstr) - ih = IntelHex(sio) - sio.close() - # test data - self.assertEqual(data, ih._buf, - "Internal buffer: %r != %r" % - (data, ih._buf)) - self.assertEqual(start_addr, ih.start_addr, - "Start address: %r != %r" % - (start_addr, ih.start_addr)) - - def test_read_rectype3(self): - self._test_read(hex_rectype3, data_rectype3, start_addr_rectype3) - - def test_read_rectype5(self): - self._test_read(hex_rectype5, data_rectype5, start_addr_rectype5) - - def _test_write(self, hexstr, data, start_addr, write_start_addr=True): - # prepare - ih = IntelHex(None) - ih._buf = data - ih.start_addr = start_addr - # write - sio = StringIO() - ih.write_hex_file(sio, write_start_addr) - s = sio.getvalue() - sio.close() - # check - self.assertEqualWrittenData(hexstr, s) - - def _test_dont_write(self, hexstr, data, start_addr): - expected = ''.join(hexstr.splitlines(True)[1:]) - self._test_write(expected, data, start_addr, False) - - def test_write_rectype3(self): - self._test_write(hex_rectype3, data_rectype3, start_addr_rectype3) - - def test_dont_write_rectype3(self): - self._test_dont_write(hex_rectype3, data_rectype3, start_addr_rectype3) - - def test_write_rectype5(self): - self._test_write(hex_rectype5, data_rectype5, start_addr_rectype5) - - def test_dont_write_rectype5(self): - self._test_dont_write(hex_rectype5, data_rectype5, start_addr_rectype5) - - def test_write_invalid_start_addr_value(self): - ih = IntelHex() - ih.start_addr = {'foo': 1} - sio = StringIO() - self.assertRaises(InvalidStartAddressValueError, ih.write_hex_file, sio) - - -class TestIntelHex_big_files(TestIntelHexBase): - """Test that data bigger than 64K read/write correctly""" - - def setUp(self): - self.f = StringIO(hex64k) - - def tearDown(self): - self.f.close() - del self.f - - def test_readfile(self): - ih = intelhex.IntelHex(self.f) - for addr, byte in dict_items_g(data64k): - readed = ih[addr] - self.assertEqual(byte, readed, - "data not equal at addr %X " - "(%X != %X)" % (addr, byte, readed)) - - def test_write_hex_file(self): - ih = intelhex.IntelHex(self.f) - sio = StringIO() - ih.write_hex_file(sio) - s = sio.getvalue() - sio.close() - self.assertEqualWrittenData(hex64k, s) - - -class TestIntelHexGetPutString(TestIntelHexBase): - - def setUp(self): - self.ih = IntelHex() - for i in range_g(10): - self.ih[i] = i - - def test_gets(self): - self.assertEqual(asbytes('\x00\x01\x02\x03\x04\x05\x06\x07'), self.ih.gets(0, 8)) - self.assertEqual(asbytes('\x07\x08\x09'), self.ih.gets(7, 3)) - self.assertRaisesMsg(intelhex.NotEnoughDataError, - 'Bad access at 0x1: ' - 'not enough data to read 10 contiguous bytes', - self.ih.gets, 1, 10) - - def test_puts(self): - self.ih.puts(0x03, asbytes('hello')) - self.assertEqual(asbytes('\x00\x01\x02hello\x08\x09'), self.ih.gets(0, 10)) - - def test_getsz(self): - self.assertEqual(asbytes(''), self.ih.getsz(0)) - self.assertRaisesMsg(intelhex.NotEnoughDataError, - 'Bad access at 0x1: ' - 'not enough data to read zero-terminated string', - self.ih.getsz, 1) - self.ih[4] = 0 - self.assertEqual(asbytes('\x01\x02\x03'), self.ih.getsz(1)) - - def test_putsz(self): - self.ih.putsz(0x03, asbytes('hello')) - self.assertEqual(asbytes('\x00\x01\x02hello\x00\x09'), self.ih.gets(0, 10)) - - def test_find(self): - self.assertEqual(0, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'))) - self.assertEqual(0, self.ih.find(asbytes('\x00'))) - self.assertEqual(3, self.ih.find(asbytes('\x03\x04\x05\x06'))) - self.assertEqual(3, self.ih.find(asbytes('\x03'))) - self.assertEqual(7, self.ih.find(asbytes('\x07\x08\x09'))) - self.assertEqual(7, self.ih.find(asbytes('\x07'))) - self.assertEqual(-1, self.ih.find(asbytes('\x0a'))) - self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'))) - self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'))) - - def test_find_start(self): - self.assertEqual(-1, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'), start=3)) - self.assertEqual(-1, self.ih.find(asbytes('\x00'), start=3)) - self.assertEqual(3, self.ih.find(asbytes('\x03\x04\x05\x06'), start=3)) - self.assertEqual(3, self.ih.find(asbytes('\x03'), start=3)) - self.assertEqual(7, self.ih.find(asbytes('\x07\x08\x09'), start=3)) - self.assertEqual(7, self.ih.find(asbytes('\x07'), start=3)) - self.assertEqual(-1, self.ih.find(asbytes('\x0a'), start=3)) - self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'), start=3)) - self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'), start=3)) - - def test_find_end(self): - self.assertEqual(-1, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'), end=4)) - self.assertEqual(0, self.ih.find(asbytes('\x00'), end=4)) - self.assertEqual(-1, self.ih.find(asbytes('\x03\x04\x05\x06'), end=4)) - self.assertEqual(3, self.ih.find(asbytes('\x03'), end=4)) - self.assertEqual(-1, self.ih.find(asbytes('\x07\x08\x09'), end=4)) - self.assertEqual(-1, self.ih.find(asbytes('\x07'), end=4)) - self.assertEqual(-1, self.ih.find(asbytes('\x0a'), end=4)) - self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'), end=4)) - self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'), end=4)) - - def test_find_start_end(self): - self.assertEqual(-1, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'), start=3, end=7)) - self.assertEqual(-1, self.ih.find(asbytes('\x00'), start=3, end=7)) - self.assertEqual(3, self.ih.find(asbytes('\x03\x04\x05\x06'), start=3, end=7)) - self.assertEqual(3, self.ih.find(asbytes('\x03'), start=3, end=7)) - self.assertEqual(-1, self.ih.find(asbytes('\x07\x08\x09'), start=3, end=7)) - self.assertEqual(-1, self.ih.find(asbytes('\x07'), start=3, end=7)) - self.assertEqual(-1, self.ih.find(asbytes('\x0a'), start=3, end=7)) - self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'), start=3, end=7)) - self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'), start=3, end=7)) - - -class TestIntelHexDump(TestIntelHexBase): - - def test_empty(self): - ih = IntelHex() - sio = StringIO() - ih.dump(sio) - self.assertEqual('', sio.getvalue()) - - def test_simple(self): - ih = IntelHex() - ih[0] = 0x12 - ih[1] = 0x34 - sio = StringIO() - ih.dump(sio) - self.assertEqual( - '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n', - sio.getvalue()) - ih[16] = 0x56 - ih[30] = 0x98 - sio = StringIO() - ih.dump(sio) - self.assertEqual( - '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n' - '0010 56 -- -- -- -- -- -- -- -- -- -- -- -- -- 98 -- |V . |\n', - sio.getvalue()) - - def test_minaddr_not_zero(self): - ih = IntelHex() - ih[16] = 0x56 - ih[30] = 0x98 - sio = StringIO() - ih.dump(sio) - self.assertEqual( - '0010 56 -- -- -- -- -- -- -- -- -- -- -- -- -- 98 -- |V . |\n', - sio.getvalue()) - - def test_start_addr(self): - ih = IntelHex() - ih[0] = 0x12 - ih[1] = 0x34 - ih.start_addr = {'CS': 0x1234, 'IP': 0x5678} - sio = StringIO() - ih.dump(sio) - self.assertEqual( - 'CS = 0x1234, IP = 0x5678\n' - '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n', - sio.getvalue()) - ih.start_addr = {'EIP': 0x12345678} - sio = StringIO() - ih.dump(sio) - self.assertEqual( - 'EIP = 0x12345678\n' - '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n', - sio.getvalue()) - - def test_bad_width(self): - ih = IntelHex() - sio = StringIO() - badwidths = [0, -1, -10.5, 2.5] - for bw in badwidths: - self.assertRaisesMsg(ValueError, "width must be a positive integer.", - ih.dump, sio, bw) - badwidthtypes = ['', {}, [], sio] - for bwt in badwidthtypes: - self.assertRaisesMsg(ValueError, "width must be a positive integer.", - ih.dump, sio, bwt) - - def test_simple_width3(self): - ih = IntelHex() - ih[0] = 0x12 - ih[1] = 0x34 - sio = StringIO() - ih.dump(tofile=sio, width=3) - self.assertEqual( - '0000 12 34 -- |.4 |\n', - sio.getvalue()) - - ih[16] = 0x56 - ih[30] = 0x98 - sio = StringIO() - ih.dump(tofile=sio, width=3) - self.assertEqual( - '0000 12 34 -- |.4 |\n' - '0003 -- -- -- | |\n' - '0006 -- -- -- | |\n' - '0009 -- -- -- | |\n' - '000C -- -- -- | |\n' - '000F -- 56 -- | V |\n' - '0012 -- -- -- | |\n' - '0015 -- -- -- | |\n' - '0018 -- -- -- | |\n' - '001B -- -- -- | |\n' - '001E 98 -- -- |. |\n', - sio.getvalue()) - - def test_minaddr_not_zero_width3_padding(self): - ih = IntelHex() - ih[17] = 0x56 - ih[30] = 0x98 - sio = StringIO() - ih.dump(tofile=sio, width=3, withpadding=True) - self.assertEqual( - '000F FF FF 56 |..V|\n' - '0012 FF FF FF |...|\n' - '0015 FF FF FF |...|\n' - '0018 FF FF FF |...|\n' - '001B FF FF FF |...|\n' - '001E 98 FF FF |...|\n', - sio.getvalue()) - - -class TestIntelHexMerge(TestIntelHexBase): - - def test_merge_empty(self): - ih1 = IntelHex() - ih2 = IntelHex() - ih1.merge(ih2) - self.assertEqual({}, ih1.todict()) - - def test_merge_simple(self): - ih1 = IntelHex({0:1, 1:2, 2:3}) - ih2 = IntelHex({3:4, 4:5, 5:6}) - ih1.merge(ih2) - self.assertEqual({0:1, 1:2, 2:3, 3:4, 4:5, 5:6}, ih1.todict()) - - def test_merge_wrong_args(self): - ih1 = IntelHex() - self.assertRaisesMsg(TypeError, 'other should be IntelHex object', - ih1.merge, {0:1}) - self.assertRaisesMsg(ValueError, "Can't merge itself", - ih1.merge, ih1) - ih2 = IntelHex() - self.assertRaisesMsg(ValueError, "overlap argument should be either " - "'error', 'ignore' or 'replace'", - ih1.merge, ih2, overlap='spam') - - def test_merge_overlap(self): - # error - ih1 = IntelHex({0:1}) - ih2 = IntelHex({0:2}) - self.assertRaisesMsg(intelhex.AddressOverlapError, - 'Data overlapped at address 0x0', - ih1.merge, ih2, overlap='error') - # ignore - ih1 = IntelHex({0:1}) - ih2 = IntelHex({0:2}) - ih1.merge(ih2, overlap='ignore') - self.assertEqual({0:1}, ih1.todict()) - # replace - ih1 = IntelHex({0:1}) - ih2 = IntelHex({0:2}) - ih1.merge(ih2, overlap='replace') - self.assertEqual({0:2}, ih1.todict()) - - def test_merge_start_addr(self): - # this, None - ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih2 = IntelHex() - ih1.merge(ih2) - self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) - # None, other - ih1 = IntelHex() - ih2 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih1.merge(ih2) - self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) - # this == other: no conflict - ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih2 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih1.merge(ih2) - self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) - # this != other: conflict - ## overlap=error - ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih2 = IntelHex({'start_addr': {'EIP': 0x87654321}}) - self.assertRaisesMsg(AddressOverlapError, - 'Starting addresses are different', - ih1.merge, ih2, overlap='error') - ## overlap=ignore - ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih2 = IntelHex({'start_addr': {'EIP': 0x87654321}}) - ih1.merge(ih2, overlap='ignore') - self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) - ## overlap=replace - ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) - ih2 = IntelHex({'start_addr': {'EIP': 0x87654321}}) - ih1.merge(ih2, overlap='replace') - self.assertEqual({'start_addr': {'EIP': 0x87654321}}, ih1.todict()) - - -class TestIntelHex16bit(TestIntelHexBase): - - def setUp(self): - self.f = StringIO(hex16) - - def tearDown(self): - self.f.close() - del self.f - - def test_init_from_file(self): - ih = intelhex.IntelHex16bit(self.f) - - def test_init_from_ih(self): - ih = intelhex.IntelHex(self.f) - ih16 = intelhex.IntelHex16bit(ih) - - def test_default_padding(self): - ih16 = intelhex.IntelHex16bit() - self.assertEqual(0x0FFFF, ih16.padding) - self.assertEqual(0x0FFFF, ih16[0]) - - def test_minaddr(self): - ih = intelhex.IntelHex16bit(self.f) - addr = ih.minaddr() - self.assertEqual(0, addr, - 'Error in detection of minaddr (0 != 0x%x)' % addr) - - def test_maxaddr(self): - ih = intelhex.IntelHex16bit(self.f) - addr = ih.maxaddr() - self.assertEqual(0x001D, addr, - 'Error in detection of maxaddr ' - '(0x001D != 0x%x)' % addr) - - def test_getitem(self): - ih = intelhex.IntelHex16bit(self.f) - ih.padding = 0x3FFF - for addr, word in enumerate(bin16): - self.assertEqual(word, ih[addr], - 'Data mismatch at address ' - '0x%x (0x%x != 0x%x)' % (addr, word, ih[addr])) - - def test_not_enough_data(self): - ih = intelhex.IntelHex() - ih[0] = 1 - ih16 = intelhex.IntelHex16bit(ih) - self.assertRaisesMsg(BadAccess16bit, - 'Bad access at 0x0: ' - 'not enough data to read 16 bit value', - lambda x: ih16[x], - 0) - - def test_write_hex_file(self): - ih = intelhex.IntelHex16bit(self.f) - sio = StringIO() - ih.write_hex_file(sio) - s = sio.getvalue() - sio.close() - - fin = StringIO(s) - ih2 = intelhex.IntelHex16bit(fin) - - self.assertEqual(ih.tobinstr(), ih2.tobinstr(), - "Written hex file does not equal with original") - - def test_bug_988148(self): - # see https://bugs.launchpad.net/intelhex/+bug/988148 - ih = intelhex.IntelHex16bit(intelhex.IntelHex()) - ih[0] = 25 - sio = StringIO() - ih.write_hex_file(sio) - - def test_setitem(self): - ih = intelhex.IntelHex16bit(self.f) - - old = ih[0] - ih[0] = old ^ 0xFFFF - - self.assertNotEqual(old, ih[0], - "Setting new value to internal buffer failed") - - def test_tobinarray(self): - ih = intelhex.IntelHex16bit() - ih[0] = 0x1234 - ih[1] = 0x5678 - self.assertEqual(array.array('H', [0x1234,0x5678,0xFFFF]), - ih.tobinarray(start=0, end=2)) - # change padding - ih.padding = 0x3FFF - self.assertEqual(array.array('H', [0x1234,0x5678,0x3FFF]), - ih.tobinarray(start=0, end=2)) -#/class TestIntelHex16bit - - -class TestIntelHexErrors(TestIntelHexBase): - """Tests for custom errors classes""" - - def assertEqualExc(self, message, exception): - return self.assertEqual(message, str(exception)) - - def test_IntelHexError(self): - self.assertEqualExc('IntelHex base error', IntelHexError()) - - def test_IntelHexError_message(self): - self.assertEqualExc('IntelHex custom error message', - IntelHexError(msg='IntelHex custom error message')) - self.assertEqualExc('IntelHex base error', IntelHexError(msg='')) - - def test_HexReaderError(self): - self.assertEqualExc('Hex reader base error', HexReaderError()) - - def test_HexRecordError(self): - self.assertEqualExc('Hex file contains invalid record at line 1', - HexRecordError(line=1)) - - def test_RecordLengthError(self): - self.assertEqualExc('Record at line 1 has invalid length', - RecordLengthError(line=1)) - - def test_RecordTypeError(self): - self.assertEqualExc('Record at line 1 has invalid record type', - RecordTypeError(line=1)) - - def test_RecordChecksumError(self): - self.assertEqualExc('Record at line 1 has invalid checksum', - RecordChecksumError(line=1)) - - def test_EOFRecordError(self): - self.assertEqualExc('File has invalid End-of-File record', - EOFRecordError()) - - def test_ExtendedSegmentAddressRecordError(self): - self.assertEqualExc( - 'Invalid Extended Segment Address Record at line 1', - ExtendedSegmentAddressRecordError(line=1)) - - def test_ExtendedLinearAddressRecordError(self): - self.assertEqualExc('Invalid Extended Linear Address Record at line 1', - ExtendedLinearAddressRecordError(line=1)) - - def test_StartSegmentAddressRecordError(self): - self.assertEqualExc('Invalid Start Segment Address Record at line 1', - StartSegmentAddressRecordError(line=1)) - - def test_StartLinearAddressRecordError(self): - self.assertEqualExc('Invalid Start Linear Address Record at line 1', - StartLinearAddressRecordError(line=1)) - - def test_DuplicateStartAddressRecord(self): - self.assertEqualExc('Start Address Record appears twice at line 1', - DuplicateStartAddressRecordError(line=1)) - - def test_InvalidStartAddressValue(self): - self.assertEqualExc("Invalid start address value: {'foo': 1}", - InvalidStartAddressValueError(start_addr={'foo': 1})) - - def test_AddressOverlapError(self): - self.assertEqualExc('Hex file has data overlap at address 0x1234 ' - 'on line 1', - AddressOverlapError(address=0x1234, line=1)) - - def test_NotEnoughDataError(self): - self.assertEqualExc('Bad access at 0x1234: ' - 'not enough data to read 10 contiguous bytes', - intelhex.NotEnoughDataError(address=0x1234, length=10)) - - def test_BadAccess16bit(self): - self.assertEqualExc('Bad access at 0x1234: ' - 'not enough data to read 16 bit value', - BadAccess16bit(address=0x1234)) -#/class TestIntelHexErrors - - -class TestDecodeHexRecords(TestIntelHexBase): - """Testing that decoding of records is correct - and all errors raised when needed - """ - - def setUp(self): - self.ih = IntelHex() - self.decode_record = self.ih._decode_record - - def tearDown(self): - del self.ih - - def test_empty_line(self): - # do we could to accept empty lines in hex files? - # standard don't say anything about this - self.decode_record('') - - def test_non_empty_line(self): - self.assertRaisesMsg(HexRecordError, - 'Hex file contains invalid record at line 1', - self.decode_record, - ' ', - 1) - - def test_short_record(self): - # if record too short it's not a hex record - self.assertRaisesMsg(HexRecordError, - 'Hex file contains invalid record at line 1', - self.decode_record, - ':', - 1) - - def test_odd_hexascii_digits(self): - self.assertRaisesMsg(HexRecordError, - 'Hex file contains invalid record at line 1', - self.decode_record, - ':0100000100F', - 1) - - def test_invalid_length(self): - self.assertRaisesMsg(RecordLengthError, - 'Record at line 1 has invalid length', - self.decode_record, - ':FF00000100', - 1) - - def test_invalid_record_type(self): - self.assertRaisesMsg(RecordTypeError, - 'Record at line 1 has invalid record type', - self.decode_record, - ':000000FF01', - 1) - - def test_invalid_checksum(self): - self.assertRaisesMsg(RecordChecksumError, - 'Record at line 1 has invalid checksum', - self.decode_record, - ':0000000100', - 1) - - def test_invalid_eof(self): - self.assertRaisesMsg(EOFRecordError, - 'File has invalid End-of-File record', - self.decode_record, - ':0100000100FE', - 1) - - def test_invalid_extended_segment(self): - # length - self.assertRaisesMsg(ExtendedSegmentAddressRecordError, - 'Invalid Extended Segment Address Record at line 1', - self.decode_record, - ':00000002FE', - 1) - # addr field - self.assertRaisesMsg(ExtendedSegmentAddressRecordError, - 'Invalid Extended Segment Address Record at line 1', - self.decode_record, - ':020001020000FB', - 1) - - def test_invalid_linear_address(self): - # length - self.assertRaisesMsg(ExtendedLinearAddressRecordError, - 'Invalid Extended Linear Address Record ' - 'at line 1', - self.decode_record, - ':00000004FC', - 1) - # addr field - self.assertRaisesMsg(ExtendedLinearAddressRecordError, - 'Invalid Extended Linear Address Record ' - 'at line 1', - self.decode_record, - ':020001040000F9', - 1) - - def test_invalid_start_segment_addr(self): - # length - self.assertRaisesMsg(StartSegmentAddressRecordError, - 'Invalid Start Segment Address Record at line 1', - self.decode_record, - ':00000003FD', - 1) - # addr field - self.assertRaisesMsg(StartSegmentAddressRecordError, - 'Invalid Start Segment Address Record at line 1', - self.decode_record, - ':0400010300000000F8', - 1) - - def test_duplicate_start_segment_addr(self): - self.decode_record(':0400000312345678E5') - self.assertRaisesMsg(DuplicateStartAddressRecordError, - 'Start Address Record appears twice at line 2', - self.decode_record, - ':0400000300000000F9', - 2) - - def test_invalid_start_linear_addr(self): - # length - self.assertRaisesMsg(StartLinearAddressRecordError, - 'Invalid Start Linear Address Record at line 1', - self.decode_record, - ':00000005FB', - 1) - # addr field - self.assertRaisesMsg(StartLinearAddressRecordError, - 'Invalid Start Linear Address Record at line 1', - self.decode_record, - ':0400010500000000F6', - 1) - - def test_duplicate_start_linear_addr(self): - self.decode_record(':0400000512345678E3') - self.assertRaisesMsg(DuplicateStartAddressRecordError, - 'Start Address Record appears twice at line 2', - self.decode_record, - ':0400000500000000F7', - 2) - - def test_addr_overlap(self): - self.decode_record(':0100000000FF') - self.assertRaisesMsg(AddressOverlapError, - 'Hex file has data overlap at address 0x0 ' - 'on line 1', - self.decode_record, - ':0100000000FF', - 1) - - def test_data_record(self): - # should be no exceptions - self.decode_record(':0100000000FF\n') - self.decode_record(':03000100000102F9\r\n') - self.decode_record(':1004E300CFF0FBE2FDF220FF20F2E120E2FBE6F396') - - def test_eof(self): - # EOF should raise special exception - self.assertRaises(_EndOfFile, self.decode_record, ':00000001FF') - -#/class TestDecodeHexRecords - - -class TestHex2Bin(unittest.TestCase): - - def setUp(self): - self.fin = StringIO(hex8) - self.fout = BytesIO() - - def tearDown(self): - self.fin.close() - self.fout.close() - - def test_hex2bin(self): - ih = hex2bin(self.fin, self.fout) - data = array.array('B', asbytes(self.fout.getvalue())) - for addr in range_g(len(bin8)): - expected = bin8[addr] - actual = data[addr] - self.assertEqual(expected, actual, - "Data different at address " - "%x (%x != %x)" % (addr, expected, actual)) - - -class TestDiffDumps(unittest.TestCase): - - def test_simple(self): - ih1 = IntelHex({1:0x30, 20:0x31, 40:0x33}) - ih2 = IntelHex({1:0x30, 20:0x32, 40:0x33}) - sio = StringIO() - intelhex.diff_dumps(ih1, ih2, sio) - result = sio.getvalue() - extra = ' ' - if sys.version_info[0] >= 3 or sys.version >= '2.7': - extra = '' - shouldbe = ( - "--- a%(extra)s\n" - "+++ b%(extra)s\n" - "@@ -1,3 +1,3 @@\n" - " 0000 -- 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- | 0 |\n" - "-0010 -- -- -- -- 31 -- -- -- -- -- -- -- -- -- -- -- | 1 |\n" - "+0010 -- -- -- -- 32 -- -- -- -- -- -- -- -- -- -- -- | 2 |\n" - " 0020 -- -- -- -- -- -- -- -- 33 -- -- -- -- -- -- -- | 3 |\n" - ) % dict(extra=extra) - self.assertEqual(shouldbe, result) - - -class TestBuildRecords(TestIntelHexBase): - - def test__from_bytes(self): - self.assertEqual(':00000001FF', - intelhex.Record._from_bytes([0,0,0,1])) - - def test_data(self): - self.assertEqual(':011234005663', intelhex.Record.data(0x1234, [0x56])) - self.assertEqual(':0312340056789059', - intelhex.Record.data(0x1234, [0x56, 0x78, 0x90])) - - def test_eof(self): - self.assertEqual(':00000001FF', intelhex.Record.eof()) - - def test_extended_segment_address(self): - self.assertEqual(':020000021234B6', - intelhex.Record.extended_segment_address(0x1234)) - - def test_start_segment_address(self): - self.assertEqual(':0400000312345678E5', - intelhex.Record.start_segment_address(0x1234, 0x5678)) - - def test_extended_linear_address(self): - self.assertEqual(':020000041234B4', - intelhex.Record.extended_linear_address(0x1234)) - - def test_start_linear_address(self): - self.assertEqual(':0400000512345678E3', - intelhex.Record.start_linear_address(0x12345678)) - - -class Test_GetFileAndAddrRange(TestIntelHexBase): - - def test_simple(self): - self.assertEqual(('filename.hex', None, None), - intelhex._get_file_and_addr_range('filename.hex')) - self.assertEqual(('f', None, None), - intelhex._get_file_and_addr_range('f')) - self.assertEqual(('filename.hex', 1, None), - intelhex._get_file_and_addr_range('filename.hex:1:')) - self.assertEqual(('filename.hex', None, 10), - intelhex._get_file_and_addr_range('filename.hex::A')) - self.assertEqual(('filename.hex', 1, 10), - intelhex._get_file_and_addr_range('filename.hex:1:A')) - self.assertEqual(('filename.hex', 1, 10), - intelhex._get_file_and_addr_range('filename.hex:0001:000A')) - - def test_bad_notation(self): - self.assertRaises(intelhex._BadFileNotation, - intelhex._get_file_and_addr_range, 'filename.hex:') - self.assertRaises(intelhex._BadFileNotation, - intelhex._get_file_and_addr_range, 'filename.hex:::') - self.assertRaises(intelhex._BadFileNotation, - intelhex._get_file_and_addr_range, 'C:\\filename.hex:', True) - - def test_drive_letter(self): - self.assertEqual(('C:\\filename.hex', None, None), - intelhex._get_file_and_addr_range('C:\\filename.hex', True)) - self.assertEqual(('C:\\filename.hex', 1, None), - intelhex._get_file_and_addr_range('C:\\filename.hex:1:', True)) - self.assertEqual(('C:\\filename.hex', None, 10), - intelhex._get_file_and_addr_range('C:\\filename.hex::A', True)) - self.assertEqual(('C:\\filename.hex', 1, 10), - intelhex._get_file_and_addr_range('C:\\filename.hex:1:A', True)) - self.assertEqual(('C:\\filename.hex', 1, 10), - intelhex._get_file_and_addr_range('C:\\filename.hex:0001:000A', True)) - - -class TestXrangeLongInt(unittest.TestCase): - - def test_xrange_longint(self): - # Bug #1408934: xrange(longint) blows with OverflowError: - if compat.Python == 2: - self.assertRaises(OverflowError, xrange, sys.maxint, sys.maxint+3) - # - upr = compat.range_g(2684625744, 2684625747) - self.assertEqual([2684625744, 2684625745, 2684625746], list(upr)) - upr = compat.range_g(2684625744, 2684625747, 2) - self.assertEqual([2684625744, 2684625746], list(upr)) - # - dnr = compat.range_g(2684625746, 2684625743, -1) - self.assertEqual([2684625746, 2684625745, 2684625744], list(dnr)) - dnr = compat.range_g(2684625746, 2684625743, -2) - self.assertEqual([2684625746, 2684625744], list(dnr)) - - -class TestInSubprocess(unittest.TestCase): - - def runProcessAndGetAsciiStdoutOrStderr(self, cmdline): - if sys.platform != 'win32': - cmdline = shlex.split(cmdline) - p = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - retcode = p.poll() - if stdout: - output = stdout.decode('ascii', 'replace') - elif stderr: - output = stderr.decode('ascii', 'replace') - output = output.replace('\r', '') - return retcode, output - - def versionChecker(self, cmdline_template): - cmdline = cmdline_template % sys.executable - retcode, output = self.runProcessAndGetAsciiStdoutOrStderr(cmdline) - self.assertEqual(version_str, output.rstrip()) - self.assertEqual(0, retcode) - - def test_setup_version(self): - self.versionChecker('%s setup.py --version') - - def test_sripts_bin2hex_version(self): - self.versionChecker('%s intelhex/scripts/bin2hex.py --version') - - def test_sripts_hex2bin_version(self): - self.versionChecker('%s intelhex/scripts/hex2bin.py --version') - - def test_sripts_hex2dump_version(self): - self.versionChecker('%s intelhex/scripts/hex2dump.py --version') - - def test_sripts_hexdiff_version(self): - self.versionChecker('%s intelhex/scripts/hexdiff.py --version') - - def test_sripts_hexmerge_version(self): - self.versionChecker('%s intelhex/scripts/hexmerge.py --version') - - -class TestWriteHexFileByteCount(unittest.TestCase): - - def setUp(self): - self.f = StringIO(hex8) - - def tearDown(self): - self.f.close() - del self.f - - def test_write_hex_file_bad_byte_count(self): - ih = intelhex.IntelHex(self.f) - sio = StringIO() - self.assertRaises(ValueError, ih.write_hex_file, sio, byte_count=0) - self.assertRaises(ValueError, ih.write_hex_file, sio, byte_count=-1) - self.assertRaises(ValueError, ih.write_hex_file, sio, byte_count=256) - - def test_write_hex_file_byte_count_1(self): - ih = intelhex.IntelHex(self.f) - ih1 = ih[:4] - sio = StringIO() - ih1.write_hex_file(sio, byte_count=1) - s = sio.getvalue() - sio.close() - # check that we have all data records with data length == 1 - self.assertEqual(( - ':0100000002FD\n' - ':0100010005F9\n' - ':01000200A25B\n' - ':01000300E517\n' - ':00000001FF\n' - ), s, - "Written hex is not in byte count 1") - # read back and check content - fin = StringIO(s) - ih2 = intelhex.IntelHex(fin) - self.assertEqual(ih1.tobinstr(), ih2.tobinstr(), - "Written hex file does not equal with original") - - def test_write_hex_file_byte_count_13(self): - ih = intelhex.IntelHex(self.f) - sio = StringIO() - ih.write_hex_file(sio, byte_count=13) - s = sio.getvalue() - # control written hex first line to check that byte count is 13 - sio.seek(0) - self.assertEqual(sio.readline(), - ':0D0000000205A2E576246AF8E6057622786E\n', - "Written hex is not in byte count 13") - sio.close() - - fin = StringIO(s) - ih2 = intelhex.IntelHex(fin) - - self.assertEqual(ih.tobinstr(), ih2.tobinstr(), - "Written hex file does not equal with original") - - def test_write_hex_file_byte_count_255(self): - ih = intelhex.IntelHex(self.f) - sio = StringIO() - ih.write_hex_file(sio, byte_count=255) - s = sio.getvalue() - # control written hex first line to check that byte count is 255 - sio.seek(0) - self.assertEqual(sio.readline(), - (':FF0000000205A2E576246AF8E60576227867300702786AE475F0011204AD02' - '04552000EB7F2ED2008018EF540F2490D43440D4FF30040BEF24BFB41A0050' - '032461FFE57760021577057AE57A7002057930070D7867E475F0011204ADEF' - '02049B02057B7403D2078003E4C207F5768B678A688969E4F577F579F57AE5' - '7760077F2012003E80F57578FFC201C200C202C203C205C206C20812000CFF' - '700D3007057F0012004FAF7AAE7922B4255FC2D5C20412000CFF24D0B40A00' - '501A75F00A787730D50508B6FF0106C6A426F620D5047002D20380D924CFB4' - '1A00EF5004C2E5D20402024FD20180C6D20080C0D20280BCD2D580BAD20580' - 'B47F2012003E20020774010E\n'), - "Written hex is not in byte count 255") - sio.close() - - fin = StringIO(s) - ih2 = intelhex.IntelHex(fin) - - self.assertEqual(ih.tobinstr(), ih2.tobinstr(), - "Written hex file does not equal with original") - -## -# MAIN -if __name__ == '__main__': - unittest.main() diff --git a/javascripts/main.js b/javascripts/main.js new file mode 100644 index 0000000..d8135d3 --- /dev/null +++ b/javascripts/main.js @@ -0,0 +1 @@ +console.log('This would be the main JS file.'); diff --git a/params.json b/params.json new file mode 100644 index 0000000..70ca7be --- /dev/null +++ b/params.json @@ -0,0 +1 @@ +{"name":"Python IntelHex library","tagline":"IntelHex files manipulating","body":"### Welcome to GitHub Pages.\r\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:\r\n\r\n```\r\n$ cd your_repo_root/repo_name\r\n$ git fetch origin\r\n$ git checkout gh-pages\r\n```\r\n\r\nIf you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.\r\n\r\n### Designer Templates\r\nWe've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.\r\n\r\n### Rather Drive Stick?\r\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\r\n\r\n### Authors and Contributors\r\nYou can @mention a GitHub username to generate a link to their profile. The resulting `` element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\r\n\r\n### Support or Contact\r\nHaving trouble with Pages? Check out the documentation at https://help.github.com/pages or contact support@github.com and we’ll help you sort it out.\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 76a844a..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,6 +0,0 @@ -# requirements for development and release process -twine # PyPi interaction, long description check in setup.py (twine check dist/intelhex-*.whl) -rst2html # documentation generation -sphinx # documentation generation -docutils # sphinx and rest2html dependency -pdoc # API documentation diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 14536a5..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -universal = 1 diff --git a/setup.py b/setup.py deleted file mode 100755 index 54d4a6d..0000000 --- a/setup.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2008-2018, Alexander Belchenko -# 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. -# * Neither the name of the author nor the names -# of its contributors may be used to endorse -# or promote products derived from this software -# without specific prior written permission. -# -# 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 OWNER 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. - -"""Setup script for IntelHex.""" - -import os, sys, glob -try: - from setuptools import setup -except ImportError: - from distutils.core import setup -from distutils.core import Command - -import intelhex, intelhex.__version__ - -LONG_DESCRIPTION = open('README.rst', 'r').read() - -SCRIPT_MODULES = [os.path.splitext(x)[0] for x in glob.glob('intelhex/scripts/*')] - -METADATA = dict( - name='intelhex', - version=intelhex.__version__.version_str, - - # Include the scripts as a subpackage - packages=['intelhex', 'intelhex.scripts'], - - # For every script file, add an entrypoint - entry_points={ - "console_scripts": [ - "{name}.py = intelhex.scripts.{name}:main".format(name=os.path.basename(x)) - for x in SCRIPT_MODULES - ] - }, - - author='Alexander Belchenko', - author_email='alexander.belchenko@gmail.com', - maintainer='Bert van Hall', - maintainer_email='bert.vanhall@gmx.de', - url='https://github.com/python-intelhex/intelhex', - description='Python library for Intel HEX files manipulations', - long_description=LONG_DESCRIPTION, - keywords='Intel HEX hex2bin HEX8', - license='BSD', - classifiers = [ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'Programming Language :: Python :: 3.13', - ], -) - - -class test(Command): - description = "unittest for intelhex" - user_options = [] - boolean_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - import unittest - import intelhex.test - verbosity = 1 - if self.verbose: - verbosity = 2 - suite = unittest.TestSuite() - loader = unittest.TestLoader() - suite.addTest(loader.loadTestsFromModule(intelhex.test)) - runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=verbosity) - result = runner.run(suite) - if result.errors or result.failures: - sys.exit(1) - - -class bench(Command): - description = "benchmarks for read/write HEX" - user_options = [ - ('repeat', 'n', 'repeat tests N times'), - ('read', 'r', 'run only tests for read operation'), - ('write', 'w', 'run only tests for write operation'), - ] - boolean_options = ['read', 'write'] - - def initialize_options(self): - self.repeat = 3 - self.read = None - self.write = None - - def finalize_options(self): - if not self.read and not self.write: - self.read = self.write = True - - def run(self): - from intelhex.bench import Measure - m = Measure(self.repeat, self.read, self.write) - m.measure_all() - m.print_report() - - -def main(): - metadata = METADATA.copy() - metadata['cmdclass'] = { - 'test': test, - 'bench': bench, # bench is out of date - } - return setup(**metadata) - -if __name__ == '__main__': - main() diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css new file mode 100644 index 0000000..e65cedf --- /dev/null +++ b/stylesheets/pygment_trac.css @@ -0,0 +1,70 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f0f3f3; } +.highlight .c { color: #0099FF; font-style: italic } /* Comment */ +.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */ +.highlight .k { color: #006699; font-weight: bold } /* Keyword */ +.highlight .o { color: #555555 } /* Operator */ +.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #009999 } /* Comment.Preproc */ +.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */ +.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ +.highlight .go { color: #AAAAAA } /* Generic.Output */ +.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #99CC66 } /* Generic.Traceback */ +.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #006699 } /* Keyword.Pseudo */ +.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #FF6600 } /* Literal.Number */ +.highlight .s { color: #CC3300 } /* Literal.String */ +.highlight .na { color: #330099 } /* Name.Attribute */ +.highlight .nb { color: #336666 } /* Name.Builtin */ +.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */ +.highlight .no { color: #336600 } /* Name.Constant */ +.highlight .nd { color: #9999FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #CC00FF } /* Name.Function */ +.highlight .nl { color: #9999FF } /* Name.Label */ +.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #003333 } /* Name.Variable */ +.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #FF6600 } /* Literal.Number.Float */ +.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */ +.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */ +.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */ +.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */ +.highlight .sc { color: #CC3300 } /* Literal.String.Char */ +.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #CC3300 } /* Literal.String.Double */ +.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */ +.highlight .si { color: #AA0000 } /* Literal.String.Interpol */ +.highlight .sx { color: #CC3300 } /* Literal.String.Other */ +.highlight .sr { color: #33AAAA } /* Literal.String.Regex */ +.highlight .s1 { color: #CC3300 } /* Literal.String.Single */ +.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */ +.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #003333 } /* Name.Variable.Class */ +.highlight .vg { color: #003333 } /* Name.Variable.Global */ +.highlight .vi { color: #003333 } /* Name.Variable.Instance */ +.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */ + +.type-csharp .highlight .k { color: #0000FF } +.type-csharp .highlight .kt { color: #0000FF } +.type-csharp .highlight .nf { color: #000000; font-weight: normal } +.type-csharp .highlight .nc { color: #2B91AF } +.type-csharp .highlight .nn { color: #000000 } +.type-csharp .highlight .s { color: #A31515 } +.type-csharp .highlight .sc { color: #A31515 } diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css new file mode 100644 index 0000000..619d19d --- /dev/null +++ b/stylesheets/stylesheet.css @@ -0,0 +1,425 @@ +/******************************************************************************* +Slate Theme for GitHub Pages +by Jason Costello, @jsncostello +*******************************************************************************/ + +@import url(pygment_trac.css); + +/******************************************************************************* +MeyerWeb Reset +*******************************************************************************/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +ol, ul { + list-style: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/******************************************************************************* +Theme Styles +*******************************************************************************/ + +body { + box-sizing: border-box; + color:#373737; + background: #212121; + font-size: 16px; + font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +h1, h2, h3, h4, h5, h6 { + margin: 10px 0; + font-weight: 700; + color:#222222; + font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; + letter-spacing: -1px; +} + +h1 { + font-size: 36px; + font-weight: 700; +} + +h2 { + padding-bottom: 10px; + font-size: 32px; + background: url('../images/bg_hr.png') repeat-x bottom; +} + +h3 { + font-size: 24px; +} + +h4 { + font-size: 21px; +} + +h5 { + font-size: 18px; +} + +h6 { + font-size: 16px; +} + +p { + margin: 10px 0 15px 0; +} + +footer p { + color: #f2f2f2; +} + +a { + text-decoration: none; + color: #007edf; + text-shadow: none; + + transition: color 0.5s ease; + transition: text-shadow 0.5s ease; + -webkit-transition: color 0.5s ease; + -webkit-transition: text-shadow 0.5s ease; + -moz-transition: color 0.5s ease; + -moz-transition: text-shadow 0.5s ease; + -o-transition: color 0.5s ease; + -o-transition: text-shadow 0.5s ease; + -ms-transition: color 0.5s ease; + -ms-transition: text-shadow 0.5s ease; +} + +a:hover, a:focus {text-decoration: underline;} + +footer a { + color: #F2F2F2; + text-decoration: underline; +} + +em { + font-style: italic; +} + +strong { + font-weight: bold; +} + +img { + position: relative; + margin: 0 auto; + max-width: 739px; + padding: 5px; + margin: 10px 0 10px 0; + border: 1px solid #ebebeb; + + box-shadow: 0 0 5px #ebebeb; + -webkit-box-shadow: 0 0 5px #ebebeb; + -moz-box-shadow: 0 0 5px #ebebeb; + -o-box-shadow: 0 0 5px #ebebeb; + -ms-box-shadow: 0 0 5px #ebebeb; +} + +p img { + display: inline; + margin: 0; + padding: 0; + vertical-align: middle; + text-align: center; + border: none; +} + +pre, code { + width: 100%; + color: #222; + background-color: #fff; + + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + font-size: 14px; + + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +pre { + width: 100%; + padding: 10px; + box-shadow: 0 0 10px rgba(0,0,0,.1); + overflow: auto; +} + +code { + padding: 3px; + margin: 0 3px; + box-shadow: 0 0 10px rgba(0,0,0,.1); +} + +pre code { + display: block; + box-shadow: none; +} + +blockquote { + color: #666; + margin-bottom: 20px; + padding: 0 0 0 20px; + border-left: 3px solid #bbb; +} + + +ul, ol, dl { + margin-bottom: 15px +} + +ul { + list-style-position: inside; + list-style: disc; + padding-left: 20px; +} + +ol { + list-style-position: inside; + list-style: decimal; + padding-left: 20px; +} + +dl dt { + font-weight: bold; +} + +dl dd { + padding-left: 20px; + font-style: italic; +} + +dl p { + padding-left: 20px; + font-style: italic; +} + +hr { + height: 1px; + margin-bottom: 5px; + border: none; + background: url('../images/bg_hr.png') repeat-x center; +} + +table { + border: 1px solid #373737; + margin-bottom: 20px; + text-align: left; + } + +th { + font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif; + padding: 10px; + background: #373737; + color: #fff; + } + +td { + padding: 10px; + border: 1px solid #373737; + } + +form { + background: #f2f2f2; + padding: 20px; +} + +/******************************************************************************* +Full-Width Styles +*******************************************************************************/ + +.outer { + width: 100%; +} + +.inner { + position: relative; + max-width: 640px; + padding: 20px 10px; + margin: 0 auto; +} + +#forkme_banner { + display: block; + position: absolute; + top:0; + right: 10px; + z-index: 10; + padding: 10px 50px 10px 10px; + color: #fff; + background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%; + font-weight: 700; + box-shadow: 0 0 10px rgba(0,0,0,.5); + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + +#header_wrap { + background: #212121; + background: -moz-linear-gradient(top, #373737, #212121); + background: -webkit-linear-gradient(top, #373737, #212121); + background: -ms-linear-gradient(top, #373737, #212121); + background: -o-linear-gradient(top, #373737, #212121); + background: linear-gradient(top, #373737, #212121); +} + +#header_wrap .inner { + padding: 50px 10px 30px 10px; +} + +#project_title { + margin: 0; + color: #fff; + font-size: 42px; + font-weight: 700; + text-shadow: #111 0px 0px 10px; +} + +#project_tagline { + color: #fff; + font-size: 24px; + font-weight: 300; + background: none; + text-shadow: #111 0px 0px 10px; +} + +#downloads { + position: absolute; + width: 210px; + z-index: 10; + bottom: -40px; + right: 0; + height: 70px; + background: url('../images/icon_download.png') no-repeat 0% 90%; +} + +.zip_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom left; +} + +.tar_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom right; + margin-left: 10px; +} + +.zip_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top left; +} + +.tar_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top right; +} + +#main_content_wrap { + background: #f2f2f2; + border-top: 1px solid #111; + border-bottom: 1px solid #111; +} + +#main_content { + padding-top: 40px; +} + +#footer_wrap { + background: #212121; +} + + + +/******************************************************************************* +Small Device Styles +*******************************************************************************/ + +@media screen and (max-width: 480px) { + body { + font-size:14px; + } + + #downloads { + display: none; + } + + .inner { + min-width: 320px; + max-width: 480px; + } + + #project_title { + font-size: 32px; + } + + h1 { + font-size: 28px; + } + + h2 { + font-size: 24px; + } + + h3 { + font-size: 21px; + } + + h4 { + font-size: 18px; + } + + h5 { + font-size: 14px; + } + + h6 { + font-size: 12px; + } + + code, pre { + min-width: 320px; + max-width: 480px; + font-size: 11px; + } + +} diff --git a/test-all-python.sh b/test-all-python.sh deleted file mode 100755 index ea49dc6..0000000 --- a/test-all-python.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -TARGETS="3.8 3.9 3.10 3.11 3.12 3.13" -DIR=$(dirname "$(readlink -f "$0")") - -_pyenv=$(command -v pyenv) -[ -z "$_pyenv" ] && { echo "pyenv is missing on your system."; exit 1; } - -_tox=$(command -v tox) -[ -z "$_tox" ] && { echo "tox is missing on your system."; exit 1; } - -cd "$DIR" - -echo "Installing (if needed) Python versions: $TARGETS" -for version in $TARGETS ; do - $_pyenv install --skip-existing $version -done - -echo "Enabling Python versions from pyenv..." -$_pyenv local $TARGETS - -echo "Running tox..." -$_tox - diff --git a/test_memory.py b/test_memory.py deleted file mode 100644 index 274e773..0000000 --- a/test_memory.py +++ /dev/null @@ -1,8 +0,0 @@ -import intelhex - -ih = intelhex.IntelHex() -for i in range(65536): ih[i] = i & 0x0FF - -print(len(ih)) - -print(ih.get_memory_size()) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index c2b7b72..0000000 --- a/tox.ini +++ /dev/null @@ -1,17 +0,0 @@ -# tox (https://tox.readthedocs.io/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py38, py39, py310, py311, py312, py313 -skip_missing_interpreters = True -tox_pyenv_fallback = False - -[testenv] -deps = - setuptools >= 72 - packaging >= 21 - -commands = - python setup.py test