diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index bc1d75a..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: cmars diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml deleted file mode 100644 index bdaab28..0000000 --- a/.github/workflows/python-publish.yml +++ /dev/null @@ -1,39 +0,0 @@ -# This workflow will upload a Python Package using Twine when a release is created -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Upload Python Package - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - deploy: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build - - name: Build package - run: python -m build - - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml deleted file mode 100644 index f29b0a6..0000000 --- a/.github/workflows/python-test.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Python Tests - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -permissions: - contents: read - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] - - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: |- - python -m pip install --upgrade pip - python -m pip install pytest - python -m pip install . - - name: Run tests - run: |- - python -m pytest tests/ -v diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1175555..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.pyc -*.swp -*.swo -/build/ -/docs/build -/.venv -/dist diff --git a/.project b/.project deleted file mode 100644 index ad1b396..0000000 --- a/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - pystdf - - - - - - - - diff --git a/pystdf/BinSummarizer.py b/BinSummarizer.py similarity index 100% rename from pystdf/BinSummarizer.py rename to BinSummarizer.py diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b0a8742..0000000 --- a/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM python:3.8.9-slim - -COPY . /app -WORKDIR /app - -RUN ["chmod", "-R", "+x", "scripts"] diff --git a/pystdf/IO.py b/IO.py similarity index 100% rename from pystdf/IO.py rename to IO.py diff --git a/pystdf/Importer.py b/Importer.py similarity index 100% rename from pystdf/Importer.py rename to Importer.py diff --git a/pystdf/Indexing.py b/Indexing.py similarity index 100% rename from pystdf/Indexing.py rename to Indexing.py diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index d511905..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/pystdf/Mapping.py b/Mapping.py similarity index 100% rename from pystdf/Mapping.py rename to Mapping.py diff --git a/pystdf/OoHelpers.py b/OoHelpers.py similarity index 100% rename from pystdf/OoHelpers.py rename to OoHelpers.py diff --git a/pystdf/ParametricSummarizer.py b/ParametricSummarizer.py similarity index 100% rename from pystdf/ParametricSummarizer.py rename to ParametricSummarizer.py diff --git a/pystdf/PartSummarizer.py b/PartSummarizer.py similarity index 100% rename from pystdf/PartSummarizer.py rename to PartSummarizer.py diff --git a/pystdf/Pipeline.py b/Pipeline.py similarity index 100% rename from pystdf/Pipeline.py rename to Pipeline.py diff --git a/README.txt b/README.txt deleted file mode 100644 index 1f17765..0000000 --- a/README.txt +++ /dev/null @@ -1,61 +0,0 @@ -=================================== -|PySTDF - The Pythonic STDF parser| -=================================== -Developed by Casey Marshall - -PySTDF is a parser for Standard Test Data Format (STDF) version 4 data files. -I wrote PySTDF to get familiar with functional programming idioms and -metaclasses in Python. As such, it uses some of the more powerful and -expressive features of the Python language. - -PySTDF is an event-based parser. As an STDF file is parsed, you recieve -record "events" in callback functions - -Refer to the provided command line scripts for ideas on how to use PySTDF: - -stdf2text, convert STDF to '|' delimited text format. -stdf2excel, convert STDF to MS Excel. -stdf_slice, an example of how to seek to a specific record offset in the STDF. - -I have also included a very basic STDF viewer GUI, StdfExplorer. I have plans -to improve upon it further in Q4 2006 - Q5 2007. - -========= -|INSTALL| -========= -Use the standard distutils setup.py. - -On Windows: "python setup.py install" -On Unix: "sudo python setup.py install" - -====== -|BUGS| -====== -PySTDF has no known bugs. However, it is my experience that every ATE vendor -has its quirks and "special interpretation" of the STDFv4 specification. - -If you find a bug in PySTDF, please send me the STDF file that demonstrates it. -This will help me improve the library. - -========= -|LICENSE| -========= -PySTDF is released under the terms and conditions of the GPL version 2 license. -You may freely use PySTDF, but you may not distribute it in closed-source -proprietary applications. Please contact me if you are interested in -purchasing an alternative license agreement to develop commercial software -with PySTDF. - -If you need some STDF consulting/development work, I might be able to help you. -I have over 5 years experience with STDF and semiconductor data analysis -systems. - -If you're in the Austin area and just want to get some lunch, that is cool too :) - -======== -|THANKS| -======== -Thanks for your interest in PySTDF. You're the reason I open-sourced it. - -Cheers, -Casey diff --git a/pystdf/SummaryStatistics.py b/SummaryStatistics.py similarity index 100% rename from pystdf/SummaryStatistics.py rename to SummaryStatistics.py diff --git a/pystdf/TableTemplate.py b/TableTemplate.py similarity index 100% rename from pystdf/TableTemplate.py rename to TableTemplate.py diff --git a/pystdf/TestSummarizer.py b/TestSummarizer.py similarity index 100% rename from pystdf/TestSummarizer.py rename to TestSummarizer.py diff --git a/pystdf/Types.py b/Types.py similarity index 100% rename from pystdf/Types.py rename to Types.py diff --git a/pystdf/V4.py b/V4.py similarity index 100% rename from pystdf/V4.py rename to V4.py diff --git a/pystdf/Writers.py b/Writers.py similarity index 100% rename from pystdf/Writers.py rename to Writers.py diff --git a/pystdf/__init__.py b/__init__.py similarity index 100% rename from pystdf/__init__.py rename to __init__.py diff --git a/data/README b/data/README deleted file mode 100644 index 146525c..0000000 --- a/data/README +++ /dev/null @@ -1,8 +0,0 @@ -The STDF files in this directory were originally provided on Galaxy -Semiconductor's website for demonstration of their tools. They were -obtained from this public URL, which I found via Google search: - -http://www.galaxysemi.com/examinator/support/install.htm - -I also welcome any user contributions of example STDF data, especially -different ATE platforms and STDF versions. diff --git a/data/demofile.stdf b/data/demofile.stdf deleted file mode 100644 index b4771e4..0000000 Binary files a/data/demofile.stdf and /dev/null differ diff --git a/data/lot2.stdf b/data/lot2.stdf deleted file mode 100644 index 7c08ea0..0000000 Binary files a/data/lot2.stdf and /dev/null differ diff --git a/data/lot3.stdf b/data/lot3.stdf deleted file mode 100644 index 5c142d4..0000000 Binary files a/data/lot3.stdf and /dev/null differ diff --git a/default.nix b/default.nix deleted file mode 100644 index d09d9ac..0000000 --- a/default.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ pkgs ? import {} }: - pkgs.mkShell { - nativeBuildInputs = with pkgs.buildPackages; [ - python38 - python38Packages.pip - python38Packages.six - python38Packages.wxPython_4_1 - ]; - shellHook = '' - [ -d .venv ] || python3 -m venv .venv - source .venv/bin/activate - ''; -} diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index c6b0515..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,153 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PySTDF.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PySTDF.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/PySTDF" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PySTDF" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html deleted file mode 100644 index fd4f968..0000000 --- a/docs/source/_templates/layout.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "!layout.html" %} -{% block extrahead %} - -{% endblock %} - diff --git a/docs/source/bugs.rst b/docs/source/bugs.rst deleted file mode 100644 index f309b9c..0000000 --- a/docs/source/bugs.rst +++ /dev/null @@ -1,13 +0,0 @@ -==== -Bugs -==== - -PySTDF has no known bugs. However, it is my experience that every ATE vendor -has its quirks and "special interpretation" of the STDFv4 specification. - -If you find a bug in PySTDF, please send me (Casey Marshall -) the STDF file that demonstrates it. -This will help me improve the library. - -You can also `open an issue `__ -on github. diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index 7e50029..0000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,241 +0,0 @@ -# -*- coding: utf-8 -*- -# -# PySTDF documentation build configuration file, created by -# sphinx-quickstart on Thu Feb 16 19:50:45 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('../../')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'PySTDF' -copyright = u'2012, Casey Marshall' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '4' -# The full version, including alpha/beta/rc tags. -release = '4' - -# 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 patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'nature' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'PySTDFdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'PySTDF.tex', u'PySTDF Documentation', - u'Casey Marshall', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'pystdf', u'PySTDF Documentation', - [u'Casey Marshall'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'PySTDF', u'PySTDF Documentation', u'Casey Marshall', - 'PySTDF', 'One line description of project.', 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index e2f9dae..0000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,43 +0,0 @@ -.. PySTDF documentation master file - -================================= -PySTDF - The Pythonic STDF parser -================================= - -**Developed by** Casey Marshall - -**Code repository** https://github.com/cmars/pystdf - -PySTDF is a parser for Standard Test Data Format (STDF) version 4 data files. -I wrote PySTDF to get familiar with functional programming idioms and -metaclasses in Python. As such, it uses some of the more powerful and -expressive features of the Python language. - -PySTDF is an event-based parser. As an STDF file is parsed, you recieve -record *events* in callback functions - -Thanks for your interest in PySTDF. You're the reason I open-sourced it. - -Cheers, -Casey - -Contents: -========= - -.. toctree:: - :maxdepth: 2 - - intro - install - sinks - pystdf_v4 - stdf - license - bugs - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/source/install.rst b/docs/source/install.rst deleted file mode 100644 index 3de9e83..0000000 --- a/docs/source/install.rst +++ /dev/null @@ -1,9 +0,0 @@ -======= -Install -======= - -Use the standard distutils setup.py. - -On Windows: "python setup.py install" -On Unix: "sudo python setup.py install" - diff --git a/docs/source/intro.rst b/docs/source/intro.rst deleted file mode 100644 index 3fcf556..0000000 --- a/docs/source/intro.rst +++ /dev/null @@ -1,5 +0,0 @@ -============ -Introduction -============ - -general introduction diff --git a/docs/source/license.rst b/docs/source/license.rst deleted file mode 100644 index 5271f36..0000000 --- a/docs/source/license.rst +++ /dev/null @@ -1,16 +0,0 @@ -======= -License -======= - -PySTDF is released under the terms and conditions of the GPL version 2 license. -You may freely use PySTDF, but you may not distribute it in closed-source -proprietary applications. Please contact me if you are interested in -purchasing an alternative license agreement to develop commercial software -with PySTDF. - -If you need some STDF consulting/development work, I might be able to help you. -I have over 5 years experience with STDF and semiconductor data analysis -systems. - -If you're in the Austin area and just want to get lunch, that is cool too :) - diff --git a/docs/source/pystdf_v4.rst b/docs/source/pystdf_v4.rst deleted file mode 100644 index ceaf887..0000000 --- a/docs/source/pystdf_v4.rst +++ /dev/null @@ -1,7 +0,0 @@ -==================================== -PySTDF stdf Version 4 record classes -==================================== - -.. automodule:: pystdf.V4 - :members: - diff --git a/docs/source/sinks.rst b/docs/source/sinks.rst deleted file mode 100644 index 651992e..0000000 --- a/docs/source/sinks.rst +++ /dev/null @@ -1,3 +0,0 @@ -===== -Sinks -===== diff --git a/docs/source/stdf.rst b/docs/source/stdf.rst deleted file mode 100644 index 7863f49..0000000 --- a/docs/source/stdf.rst +++ /dev/null @@ -1,455 +0,0 @@ -=========================================================== -Standard Test Data Format (STDF Specification Version 4) -=========================================================== - -Introduction to STDF -==================== -As the ATE industry matures, many vendors offer networking systems that -complement the test systems themselves and help customers get more out of their -ATE investment. Many of these networking systems are converging on popular -standards, such as EthernetÛ . A glaring hole in these standards has been -the lack of test result data compatibility between test systems of different -manufacturers, and sometimes within the product lines of a single manufacturer. -In order to help overcome this problem, Teradyne has developed a simple, -flexible, portable data format to which existing data files and formats -can be easily and economically converted. Called the Standard Test Data -Format (STDFÛ ), its specification is contained in the following document. -It is our hope that both users and manufacturers of semiconductor ATE will -find this standard useful, and will incorporate it into their own operations -and products. Teradyne has adopted this standard for the test result output -of all of its UNIXÛ operating system based testers, and offers conversion -software for users of its Test System Director for our other semiconductor -test systems. Teradyne derives no direct commercial benefit from propagating -this standard, but we hope its usefulness, thoroughness, and full documentation -will make all of us who work with ATE more productive. - - -Teradyne's Use of the STDF Specification ----------------------------------------- -The Standard Test Data Format is intended as a comprehensive standard for the -entire ATE industry, not as a description of how Teradyne writes or analyzes -test result data. A test system can support STDF without using all the STDF -record types or filling in all the fields of the record types it does use. -Similarly, when the specification says that an STDF record type can be used -to create a certain report, it cannot be assumed that Teradyne data analysis -software always uses the record type to create its reports. In addition, -the statement that a field or record is required or optional applies only -to the definition of a valid STDF file; data analysis software may require a -field that is declared optional in the specification. For this reason, the -STDF specification is not the final reference on how any piece of Teradyne -software implements the specification. To determine how a Teradyne test -system fills in the STDF record types, please refer to the documentation -for that test system's executive software. To determine what STDF fields -are used by a Teradyne data analysis tool, refer to the documentation for -the data analysis product. - -STDF Design Objectives -====================== -As ATE networking continues to emerge into a heterogeneous environment -involving various sophisticated computers and operating systems, it becomes -necessary to define a common ground that allows testers, database and database -management systems, and data analysis software to store and communicate test -data in a form that is useful, general, and flexible. - -The Standard Test Data Format (STDF) described in this document provides -such a form. STDF is flexible enough to meet the needs of the different -testers that generate raw test data, the databases that store the data, and -the data analysis programs that use the data. The fact that it is a single, -coherent standard also facilitates the sharing and communicating of the data -among these various components of the complete ATE system. - -STDF is not an attempt to specify a database architecture for either testers -or the centralized database engines. Instead, it is a set of logical record -types. Because data items are described in terms of logical record types, -the record types can be used as the underlying data abstraction, whether the -data resides in a data buffer, resides on a mass storage device, or is being -propagated in a network message. It is independent of network or database -architecture. Furthermore, the STDF logical record types may be treated as a -convenient data object by any of the software, either networking or database, -that may be used on a tester or database engine. - -Using a standard but flexible test data format makes it possible for a single -data formatting program running on the centralized database engine to accept -data from a wide range of testers, whether the testers come from one vendor -or from different vendors or are custom-built by the ATE user. In addition, -adherence to a standard format permits the exporting of data from the central -database and data analysis engine to the user's in-house network for further -analysis in a form that is well documented and thoroughly debugged. Finally, -the standard makes it possible to develop portable software for data reporting -and analysis on both the testers and the centralized database engine. - - -The following list summarizes the major objectives that guided the design -of STDF: - -* Be capable of storing test data for all semiconductor testers and trimmers. -* Provide a common format for storage and transmission of data. -* Provide a basis for portable data reporting and analysis software. -* Decouple data message format and database format to allow enhancements to - either, independently of the other. -* Provide support for optional (missing or invalid) data. -* Provide complete and concise documentation for developers and users. -* Make it easy for customers to write their own reports or reformat data for - their own database. - -STDF is already a standard within Teradyne: - -* All Teradyne semiconductor testers produce raw data in a format that conforms - to STDF. -* The Manufacturing Data Pipeline and Insight Series software can process any - data written in conformance with STDF. - -STDF Record Structure -===================== -This section describes the basic STDF V4 record structure. - -It describes the following general topics, which -are applicable to all the record types: - -* STDF record header -* Record types and subtypes -* Data type codes and representation -* Optional fields and missing/invalid data - -STDF Record Header ------------------- - -Each STDF record begins with a record header consisting of the following -three fields: - -======= ======================================================================= -Field Description -======= ======================================================================= -REC_LEN The number of bytes of data following the record header. REC_LEN does - not include the four bytes of the record header. -REC_TYP An integer identifying a group of related STDF record types. -REC_SUB An integer identifying a specific STDF record type within each REC_TYP - group. On REC_TYP and REC_SUB , see the next section. -======= ======================================================================= - -Record Types and Subtypes -------------------------- - -The header of each STDF record contains a pair of fields called **REC_TYP** and -**REC_SUB**. Each **REC_TYP** value identifies a group of related STDF record -types. Each **REC_SUB** value identifies a single STDF record type within a -**REC_TYP** group. The combination of **REC_TYP** and **REC_SUB** values -uniquely identifies each record type. This design allows groups of related -records to be easily identified by data analysis programs, while providing -unique identification for each type of record in the file. - -All **REC_TYP** and **REC_SUB** codes less than 200 are reserved for future use -by Teradyne. All codes greater than 200 are available for custom applications -use. The codes are all in decimal values. The official list of codes and -documentation for their use is maintained by Teradyne's Semiconductor CIM -Division (SCD). - -The following table lists the meaning of the **REC_TYP** codes currently defined -by Teradyne, as well as the **REC_SUB** codes defined in the STDF specification. - -======= ================================================================== -REC_TYP Meaning and STDFREC_SUB Codes -======= ================================================================== -0 Information about the STDF file - * 10 File Attributes Record (FAR - :class:`pystdf.V4.Far`) - * 20 Audit Trail Record (ATR - :class:`pystdf.V4.Atr`) -1 Data collected on a per lot basis - * 10 Master Information Record (MIR - :class:`pystdf.V4.Mir`) - * 20 Master Results Record (MRR - :class:`pystdf.V4.Mrr`) - * 30 Part Count Record (PCR - :class:`pystdf.V4.Pcr`) - * 40 Hardware Bin Record (HBR - :class:`pystdf.V4.Hbr`) - * 50 Software Bin Record (SBR - :class:`pystdf.V4.Sbr`) - * 60 Pin Map Record (PMR - :class:`pystdf.V4.Pmr`) - * 62 Pin Group Record (PGR - :class:`pystdf.V4.Pgr`) - * 63 Pin List Record (PLR - :class:`pystdf.V4.Plr`) - * 70 Retest Data Record (RDR - :class:`pystdf.V4.Rdr`) - * 80 Site Description Record (SDR - :class:`pystdf.V4.Sdr`) -2 Data collected per wafer - * 10 Wafer Information Record (WIR - :class:`pystdf.V4.Wir`) - * 20 Wafer Results Record (WRR - :class:`pystdf.V4.Wrr`) - * 30 Wafer Configuration Record (WCR - :class:`pystdf.V4.Wcr`) -5 Data collected on a per part basis - * 10 Part Information Record (PIR - :class:`pystdf.V4.Pir`) - * 20 Part Results Record (PRR - :class:`pystdf.V4.Prr`) -10 Data collected per test in the test program - * 30 Test Synopsis Record (TSR - :class:`pystdf.V4.Tsr` ) -15 Data collected per test execution - * 10 Parametric Test Record (PTR - :class:`pystdf.V4.Ptr`) - * 15 Multiple-Result Parametric Record (MPR - :class:`pystdf.V4.Mpr`) - * 20 Functional Test Record (FTR - :class:`pystdf.V4.Ftr`) -20 Data collected per program segment - * 10 Begin Program Section Record (BPS - :class:`pystdf.V4.Bps`) - * 20 End Program Section Record (EPS - :class:`pystdf.V4.Eps`) -50 Generic Data - * 10 Generic Data Record (GDR - :class:`pystdf.V4.Gdr`) - * 30 Datalog Text Record (DTR - :class:`pystdf.V4.Dtr`) -180 Reserved for use by Image software -181 Reserved for use by IG900 software -======= ================================================================== - -Data Type Codes and Representation ----------------------------------- - -The STDF specification uses a set of data type codes that are concise and -easily recognizable. For example, R*4 indicates a REAL (float) value stored -in four bytes. A byte consists of eight bits of data. For purposes of this -document, the low order bit of each byte is designated as bit 0 and the high -order bit as bit 7. The following table gives the complete list of STDF data -type codes, as well as the equivalent C language type specifier. - -====== =================================================== =================== -Code Description C Type Specifier -====== =================================================== =================== -C*12 Fixed length character string: char[12] - If a fixed length character string does not fill - the entire field, it must be left-justified and - padded with spaces. -C*n Variable length character string: char[] - first byte = unsigned count of bytes to follow - (maximum of 255 bytes) -C*f Variable length character string: char[] - string length is stored in another field -U*1 One byte unsigned integer unsigned char -U*2 Two byte unsigned integer unsigned short -U*4 Four byte unsigned integer unsigned long -I*1 One byte signed integer char -I*2 Two byte signed integer short -I*4 Four byte signed integer long -R*4 Four byte floating point number float -R*8 Eight byte floating point number long float (double) -B*6 Fixed length bit-encoded data char[6] -V*n Variable data type field: - The data type is specified by a code in the - first byte, and the data follows - (maximum of 255 bytes) -B*n Variable length bit-encoded field: char[] - First byte = unsigned count of bytes to follow - (maximum of 255 bytes). - First data item in least significant bit of the - second byte of the array (first byte is count.) -D*n Variable length bit-encoded field: char[] - First two bytes = unsigned count of bits to - follow (maximum of 65,535 bits). - First data item in least significant bit of the - third byte of the array (first two bytes are - count). - Unused bits at the high order end of the last - byte must be zero. -N*1 Unsigned integer data stored in a nibble. char - First item in low 4 bits, second item in high - 4 bits. If an odd number of nibbles is indicated, - the high nibble of the byte will be zero. Only - whole bytes can be written to the STDF file. -kxTYPE Array of data of the type specified. TYPE[] - The value of *k* (the number of elements in the - array) is defined in an earlier field in the - record. For example, an array of short unsigned - integers is defined as kxU*2. -====== =================================================== =================== - -Note on Time and Date Usage -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The date and time field used in this specification is defined as a four byte -(32 bit) unsigned integer field measuring the number of seconds since midnight -on January 1st, 1970, in the local time zone. This is the UNIX standard base -time, adjusted to the local time zone. Refer to the Glossary for definitions -of Setup time, Start time, and Finish time as used in STDF. - -Note on Data Representation -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When data is shared among systems with unlike central processors, the problem -arises that there is little or no standardization of data representation (that -is, the bit ordering of various data types) among the various processors of -the world. For example, the data representations for DEC, Motorola, Intel, -and IBM computers are all different, even though at least two of them adhere -to the IEEE floating point standard. Moreover, different processors made by -the same company sometimes store data in incompatible ways. - -To address this problem, the STDF specification uses a field calledCPU_TYPE in -the File Attributes Record (FAR). This field indicates the type of processor -that wrote the data (for example, Sun series or DEC-11 series). The field -is used as follows: - -* When writing an STDF file, a system uses its own native data representation. - The type of the writing processor is stored in theCPU_TYPE field. -* When reading an STDF file, a system must convert the records to its own - native data representation as it reads them, if necessary. To do so, it checks - the value of the CPU_TYPE field in the FAR, which is the first record in the - file. Then, if the writing CPU's data representation - is incompatible with its own, it uses a subroutine that reads the next (or - selected) record and converts the records to its own data representation as - it reads them. - -This approach has the following advantages: - -* All testers, trimmers, and hosts can read and write local data using their - native data representation. -* Testing and local data analysis are not slowed down by performing data - conversions on any tester. -* Use of a read subroutine makes data conversion transparent at read time. - -This approach works for any combination of host and tester processors, provided -that the machines are capable of storing and reading the test data in eight bit -bytes. - -Optional Fields and Missing/Invalid Data ----------------------------------------- - -Certain fields in STDF records are defined as optional. An optional field -must be present in the record, but there are ways to indicate that its value -is not meaningful, that is, that its data should be considered missing or -invalid. There are two such methods: - -* Some optional fields have a predefined value that means that the data for the - field is missing. For example, if the optional field is a variable-length - character string, a length byte of 0 means that the data is missing. If - the field is numeric, a value of -1 may be defined as meaning that the - data is missing. -* For other optional fields, all possible stored values, including -1, are - legal. In this case, the STDF specification for the record defines an - Optional Data bit field. Each bit is used to designate whether an optional - field in the record contains valid or invalid data. Usually, if the bit - for an optional field is set, any data in the field is invalid and should - be ignored. - -Optional fields at the end of a record may be omitted in order to save space -on the storage medium. To be omitted, an optional field must have missing -or invalid data, and all the fields following it must be optional fields -containing missing or invalid data. It is never legal to omit an optional -field from the middle of the record. - -The specification of each STDF record has a column labelled **Missing/Invalid -Data Flag**.An entry in this column means that the field is optional, and that -the value shown is the way to flag the field's data as missing or invalid. If -the column does not have an entry, the field is required. - -Each data type has a standard way of indicating missing or invalid data, -as the following table shows: - -+-------------------------------+--------------------------------------------+ -| Data Type | Missing/Invalid Data Flag | -+===============================+============================================+ -| Variable-length string | Set the length byte to 0. | -+-------------------------------+--------------------------------------------+ -| Fixed-length character string | Fill the field with spaces. | -+-------------------------------+--------------------------------------------+ -| Fixed-length binary string | Set a flag bit in an Optional Data byte. | -+-------------------------------+--------------------------------------------+ -| Time and date fields | Use a binary 0. | -+-------------------------------+--------------------------------------------+ -| Signed and unsigned integers | Use the indicated reserved value | -| and floating point values | or set a flag bit in an OptionalDatabyte. | -+-------------------------------+--------------------------------------------+ - -Note on *Required* and *Optional* -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The distinction between required and optional fields applies only to the -definition of a minimally valid STDF file.Itis not a statement about whether -any software (even Teradyne software) requires the field. A field that -is marked optional in the specification may be required by software that -reads or analyzes the STDF file, even if Teradyne has written the software. -In most cases, a minimally valid STDF file will not provide sufficient input -for a piece of analysis software. You will need to fill in some fields or -records that are not marked as required here. This specification is not -intended to define the data requirements for any analysis software. The only -authority on whether a piece of software requires a certain STDF field or -record is the documentation for that software. - - -STDF Record Types -================= - -This section contains the definitions for the STDF record types. The following -information is provided for each record type: - -* a statement of function: how the record type is used in the STDF file. -* a table defining the data fields: first the standard STDF header, then the - fields specific to this record type. The information includes the field name, - the data type (see the previous section for the data type codes), a brief - description of the field, and the flag to indicate missing or invalid data - (see the previous section for a discussion of optional fields). -* any additional notes on specific fields. -* possible uses for this record type in data analysis reports. Note that this - entry states only where the record type can be used. It is not a statement - that the reports listed always use this record type, even if Teradyne has - written those reports. For definitive information on how any data analysis - software uses the STDF file, see the documentation for the data analysis - software. -* frequency with which the record type appears in the STDF file: for example, - once per lot, once per wafer, one per test, and so forth. -* the location of the record type in the STDF file. See the note on - *initial sequence* on the next page. - -Note on *Initial Sequence* --------------------------- - -For several record types, the *Location* says that the record must appear -*after the initial sequence*. The phrase *initial sequence* refers to -therecords that must appear at thebeginning of the STDFfile. The requirements -for the initial sequence are as follows: - -* Every file must contain one File Attributes Record (FAR), one Master - Information Record (MIR), one or more Part Count Records (PCR), and one - Master Results Record (MRR ). All other records are optional. -* The first record in the STDF file must be the File Attributes Record (FAR). -* If one or more Audit Trail Records (ATRs) are used, they must appear - immediately after the FAR. -* The Master Information Record (MIR) must appear in every - STDF file. Its location must be after the FAR and the ATR s(if ATRs are used). -* If the Retest Data Record (RDR ) is used, it must appear immediately - after the MIR. -* If one or more Site Description Records (SDRs) are used, - they must appear immediately after the MIR and RDR (if the RDR is used). - -Given these requirements, every STDF record must contain one of these -initial sequences: - -* FAR - MIR -* FAR - ATRs - MIR -* FAR - MIR- RDR -* FAR - ATRs - MIR- RDR -* FAR - MIR - SDRs -* FAR - ATRs - MIR - SDRs -* FAR - MIR- RDR - SDRs -* FAR - ATRs - MIR- RDR- SDRs - -All other STDF record types appear after the initial sequence. - -Alphabetical Listing --------------------- - -In this section, the STDF record types appear in order of ascending record -type and record subtype codes. For easier reference, the record types are -listed on this page in alphabetical order, by the three-letter abbreviations -for the record types. - -====== ==================================== ============ -Record Type PySTDF Class -====== ==================================== ============ -ATR Audit Trail Record :class:`pystdf.V4.Atr` -BPS Begin Program Section Record :class:`pystdf.V4.Bps` -DTR Datalog Text Record :class:`pystdf.V4.Dtr` -EPS End Program Section Record :class:`pystdf.V4.Eps` -FAR File Attributes Record :class:`pystdf.V4.Far` -FTR Functional Test Record :class:`pystdf.V4.Ftr` -GDR Generic Data Record :class:`pystdf.V4.Gdr` -HBR Hardware Bin Record :class:`pystdf.V4.Hbr` -MIR Master Information Record :class:`pystdf.V4.Mir` -MPR Multiple-Result Parametric Record :class:`pystdf.V4.Mpr` -MRR Master Results Record :class:`pystdf.V4.Mrr` -PCR Part Count Record :class:`pystdf.V4.Pcr` -PGR Pin Group Record :class:`pystdf.V4.Pgr` -PIR Part Information Record :class:`pystdf.V4.Pir` -PLR Pin List Record :class:`pystdf.V4.Plr` -PMR Pin Map Record :class:`pystdf.V4.Pmr` -PRR Part Results Record :class:`pystdf.V4.Prr` -PTR Parametric Test Record :class:`pystdf.V4.Ptr` -RDR Retest Data Record :class:`pystdf.V4.Rdr` -SBR Software Bin Record :class:`pystdf.V4.Sbr` -SDR Site Description Record :class:`pystdf.V4.Sdr` -TSR Test Synopsis Record :class:`pystdf.V4.Tsr` -WCR Wafer Configuration Record :class:`pystdf.V4.Wcr` -WIR Wafer Information Record :class:`pystdf.V4.Wir` -WRR Wafer Results Record :class:`pystdf.V4.Wrr` -====== ==================================== ============ - diff --git a/pystdf/logexcept.py b/logexcept.py similarity index 100% rename from pystdf/logexcept.py rename to logexcept.py diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 80cd34e..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,53 +0,0 @@ -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[project] -name = "pystdf" -version = "1.3.4" -description = "Python module for working with STDF files" -readme = {content-type = "text/plain", text = """ -PySTDF is a Python module that makes it easy to work with STDF (Teradyne"s Standard Test Data Format). STDF is a commonly used file format in semiconductor test -- automated test equipment (ATE) from such vendors as Teradyne, Verigy, LTX, Credence, and others support this format. - -PySTDF provides event-based stream parsing of STDF version 4, along with indexers that can help you rearrange the data into a more useful tabular form, as well as generate missing summary records or new types of derivative records. - -The parser architecture is very flexible and can easily be extended to support STDF version 3 as well as custom record types. - -Potential applications of PySTDF include: -* Debugging a vendor"s STDF implementation -* Straight conversion to ASCII-readable form -* Repairing STDF files -* Developing an application that leverages STDF - - Conversion to tabular form for statistical analysis tools - - Loading data into a relational database - -PySTDF is released under a GPL license. Applications developed with PySTDF can only be released with a GPL-compatible license. Commercial applications can purchase an alternate license agreement for closed-source distribution. -"""} -authors = [{name = "Casey Marshall", email="casey.marshall@gmail.com"}] -url="https://github.com/cmars/pystdf" -dependencies = [ - 'numpy', - 'pandas', - 'openpyxl', -] -packages=["pystdf", "pystdf.scripts"] -classifiers=[ - "Development Status :: 4 - Beta", - "Environment :: Console", - "License :: Free for non-commercial use", - "License :: OSI Approved :: GNU General Public License (GPL)", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Intended Audience :: Manufacturing", - "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", - "Topic :: Utilities", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Software Development :: Pre-processors", -] - -[project.scripts] -stdf_slice = "pystdf.scripts.stdf_slice:main" -rec_index = "pystdf.scripts.rec_index:main" -stdf2excel = "pystdf.scripts.stdf2excel:main" -stdf2text = "pystdf.scripts.stdf2text:main" -stdf2xml = "pystdf.scripts.stdf2xml:main" diff --git a/pystdf/scripts/__init__.py b/scripts/__init__.py similarity index 100% rename from pystdf/scripts/__init__.py rename to scripts/__init__.py diff --git a/pystdf/scripts/rec_index.py b/scripts/rec_index.py similarity index 100% rename from pystdf/scripts/rec_index.py rename to scripts/rec_index.py diff --git a/pystdf/scripts/stdf2excel.py b/scripts/stdf2excel.py similarity index 56% rename from pystdf/scripts/stdf2excel.py rename to scripts/stdf2excel.py index 44641c7..fe1321c 100644 --- a/pystdf/scripts/stdf2excel.py +++ b/scripts/stdf2excel.py @@ -17,26 +17,42 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -# Modified: 2017 Minh-Hai Nguyen +# Modified: 2025 Hassan Sheikh # + import sys, os from pystdf.Importer import STDF2DataFrame import pystdf.V4 as V4 import pandas as pd +import re + +def clean_invalid_excel_chars(val): + if isinstance(val, str): + # Remove characters not allowed in Excel (control chars) + return re.sub(r'[\000-\010\013-\014\016-\037]', '', val) + return val + +def toExcel(fname, tables): + """ Export the tables from tables to Excel with data cleaning """ + with pd.ExcelWriter(fname, engine='openpyxl') as writer: + for k, v in tables.items(): + record = [r for r in V4.records if r.__class__.__name__.upper() == k] + if not record: + print(f"Ignore exporting table {k}: No such record type exists.") + continue -def toExcel(fname,tables): - """ Export the tables from toTables to Excel - """ - with pd.ExcelWriter(fname) as writer: - for k,v in tables.items(): - # Make sure the order of columns complies the specs - record = [r for r in V4.records if r.__class__.__name__.upper()==k] - if len(record)==0: - print("Ignore exporting table %s: No such record type exists." %k) + expected_columns = [field[0] for field in record[0].fieldMap] + + existing_columns = [col for col in expected_columns if col in v.columns] + + if existing_columns: + # Clean DataFrame values + v_clean = v[existing_columns].map(clean_invalid_excel_chars) + v_clean.to_excel(writer, sheet_name=k, index=False, na_rep="N/A") else: - columns = [field[0] for field in record[0].fieldMap] - v.to_excel(writer,sheet_name=k,columns=columns,index=False,na_rep="N/A") + print(f"No matching columns found for record {k}, skipping export.") + def main(): if len(sys.argv)==1: diff --git a/pystdf/scripts/stdf2text.py b/scripts/stdf2text.py similarity index 96% rename from pystdf/scripts/stdf2text.py rename to scripts/stdf2text.py index 6732436..4f1ab2c 100644 --- a/pystdf/scripts/stdf2text.py +++ b/scripts/stdf2text.py @@ -36,8 +36,8 @@ from pystdf.Writers import TextWriter import pystdf.V4 -gzPattern = re.compile('\.g?z', re.I) -bz2Pattern = re.compile('\.bz2', re.I) +gzPattern = re.compile(r'g?z', re.I) +bz2Pattern = re.compile(r'bz2', re.I) def process_file(fnames): filename = fnames[0] diff --git a/pystdf/scripts/stdf2xml.py b/scripts/stdf2xml.py similarity index 60% rename from pystdf/scripts/stdf2xml.py rename to scripts/stdf2xml.py index c6192e9..d6b3891 100644 --- a/pystdf/scripts/stdf2xml.py +++ b/scripts/stdf2xml.py @@ -36,39 +36,47 @@ from pystdf.Writers import XmlWriter import pystdf.V4 -gzPattern = re.compile('\.g?z', re.I) -bz2Pattern = re.compile('\.bz2', re.I) +gzPattern = re.compile(r'\.g?z', re.I) +bz2Pattern = re.compile(r'\.bz2', re.I) -def process_file(fn): - filename, = sys.argv[1:] +def process_file(fnames): + input_file = fnames[0] + output_file = fnames[1] if len(fnames) > 1 else None reopen_fn = None - if filename is None: - f = sys.stdin - elif gzPattern.search(filename): + if gzPattern.search(input_file): if not have_gzip: - print("gzip is not supported on this system", file=sys.stderr) + print("gzip not supported", file=sys.stderr) sys.exit(1) - reopen_fn = lambda: gzip.open(filename, 'rb') + reopen_fn = lambda: gzip.open(input_file, 'rb') f = reopen_fn() - elif bz2Pattern.search(filename): + elif bz2Pattern.search(input_file): if not have_bz2: - print("bz2 is not supported on this system", file=sys.stderr) + print("bz2 not supported", file=sys.stderr) sys.exit(1) - reopen_fn = lambda: bz2.BZ2File(filename, 'rb') + reopen_fn = lambda: bz2.BZ2File(input_file, 'rb') f = reopen_fn() else: - f = open(filename, 'rb') - p=Parser(inp=f, reopen_fn=reopen_fn) - p.addSink(XmlWriter()) - p.parse() + f = open(input_file, 'rb') + + p = Parser(inp=f, reopen_fn=reopen_fn) + + # Handle output file + if output_file: + with open(output_file, 'w') as fout: + p.addSink(XmlWriter(stream=fout)) + p.parse() + else: + p.addSink(XmlWriter()) + p.parse() + f.close() def main(): if len(sys.argv) < 2: - print("Usage: %s " % (sys.argv[0])) + print(f"Usage: {sys.argv[0]} [output xml file]") else: - process_file(sys.argv[1]) + process_file(sys.argv[1:]) if __name__ == '__main__': main() diff --git a/scripts/stdf_conversions.zip b/scripts/stdf_conversions.zip new file mode 100644 index 0000000..add496c Binary files /dev/null and b/scripts/stdf_conversions.zip differ diff --git a/pystdf/scripts/stdf_slice.py b/scripts/stdf_slice.py similarity index 100% rename from pystdf/scripts/stdf_slice.py rename to scripts/stdf_slice.py diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/test_BinSummarizer.py b/tests/test_BinSummarizer.py deleted file mode 100644 index ae806f9..0000000 --- a/tests/test_BinSummarizer.py +++ /dev/null @@ -1,94 +0,0 @@ -import unittest -from pystdf.BinSummarizer import BinSummarizer -from pystdf.V4 import prr, hbr, sbr - -class MockDataSource: - def __init__(self): - self.name = "MockDataSource" - -class TestBinSummarizer(unittest.TestCase): - def setUp(self): - self.summarizer = BinSummarizer() - self.dataSource = MockDataSource() - self.summarizer.before_begin(self.dataSource) - - def test_flags(self): - # Test hard bin flags - hbr_row = [0] * len(hbr.fieldNames) - hbr_row[hbr.HBIN_PF] = 'F' - self.assertEqual(self.summarizer.getHPfFlags(hbr_row), BinSummarizer.FLAG_FAIL) - - hbr_row[hbr.HBIN_PF] = 'P' - self.assertEqual(self.summarizer.getHPfFlags(hbr_row), 0) - - hbr_row[hbr.HBIN_PF] = 'X' - self.assertEqual(self.summarizer.getHPfFlags(hbr_row), BinSummarizer.FLAG_UNKNOWN) - - # Test soft bin flags - sbr_row = [0] * len(sbr.fieldNames) - sbr_row[sbr.SBIN_PF] = 'F' - self.assertEqual(self.summarizer.getSPfFlags(sbr_row), BinSummarizer.FLAG_FAIL) - - sbr_row[sbr.SBIN_PF] = 'P' - self.assertEqual(self.summarizer.getSPfFlags(sbr_row), 0) - - sbr_row[sbr.SBIN_PF] = 'X' - self.assertEqual(self.summarizer.getSPfFlags(sbr_row), BinSummarizer.FLAG_UNKNOWN) - - def test_bin_storage(self): - # Test HBR storage - hbr_row = [0] * len(hbr.fieldNames) - hbr_row[hbr.HEAD_NUM] = 255 # Overall bin - hbr_row[hbr.HBIN_NUM] = 1 - self.summarizer.onHbr(hbr_row) - self.assertEqual(len(self.summarizer.getOverallHbins()), 1) - - hbr_row[hbr.HEAD_NUM] = 1 # Site-specific bin - hbr_row[hbr.SITE_NUM] = 1 - self.summarizer.onHbr(hbr_row) - self.assertEqual(len(self.summarizer.getSiteHbins()), 1) - - # Test SBR storage - sbr_row = [0] * len(sbr.fieldNames) - sbr_row[sbr.HEAD_NUM] = 255 # Overall bin - sbr_row[sbr.SBIN_NUM] = 1 - self.summarizer.onSbr(sbr_row) - self.assertEqual(len(self.summarizer.getOverallSbins()), 1) - - sbr_row[sbr.HEAD_NUM] = 1 # Site-specific bin - sbr_row[sbr.SITE_NUM] = 1 - self.summarizer.onSbr(sbr_row) - self.assertEqual(len(self.summarizer.getSiteSbins()), 1) - - def test_part_tracking(self): - prr_row = [0] * len(prr.fieldNames) - prr_row[prr.SITE_NUM] = 1 - prr_row[prr.HARD_BIN] = 1 - prr_row[prr.SOFT_BIN] = 1 - prr_row[prr.PART_FLG] = 0 # Pass - - # Test part counting and pass/fail tracking - self.summarizer.onPrr(prr_row) - - # Check hard bin tracking - count, status = self.summarizer.hbinParts[(1, 1)] - self.assertEqual(count[0], 1) - self.assertEqual(status[0], 'P') - - # Check soft bin tracking - count, status = self.summarizer.sbinParts[(1, 1)] - self.assertEqual(count[0], 1) - # Soft bins initialize with False, so they'll get ' ' status - self.assertEqual(status[0], ' ') - - # Test fail case - prr_row[prr.PART_FLG] = 0x08 # Fail - self.summarizer.onPrr(prr_row) - - # Check status becomes mixed (' ') when both pass and fail seen - count, status = self.summarizer.hbinParts[(1, 1)] - self.assertEqual(count[0], 2) - self.assertEqual(status[0], ' ') - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_IO.py b/tests/test_IO.py deleted file mode 100644 index a522540..0000000 --- a/tests/test_IO.py +++ /dev/null @@ -1,140 +0,0 @@ -import unittest -import io -import sys -from pystdf.IO import Parser, appendFieldParser -from pystdf.Types import RecordHeader, EofException, EndOfRecordException -from pystdf import V4 - -class TestIO(unittest.TestCase): - def setUp(self): - sys.stderr.write('Setting up test...\n') - self.test_stream = io.BytesIO() - self.parser = Parser(recTypes=V4.records, inp=self.test_stream, endian='<') - self.parser.eof = 0 # Reset EOF flag - sys.stderr.write('Setup complete.\n') - - def write_to_stream(self, data): - """Helper method to write bytes to the test stream and reset position""" - self.test_stream.write(data) - self.test_stream.seek(0) - - def test_read_field_types(self): - sys.stderr.write('Starting field types test...\n') - # Set up header - header = RecordHeader() - - # Test U1 (unsigned 1-byte integer) - test_data = bytes([42]) - self.write_to_stream(test_data) - header.len = 1 - value = self.parser.readField(header, "U1") - sys.stderr.write(f'U1 value: {value}\n') - self.assertEqual(value, 42) - - def test_read_header(self): - header_data = bytes([ - 0x0A, 0x00, # Length (10) - 0x15, # Type (21) - 0x20 # Sub-type (32) - ]) - self.write_to_stream(header_data) - header = self.parser.readHeader() - self.assertEqual(header.len, 10) - self.assertEqual(header.typ, 21) - self.assertEqual(header.sub, 32) - - def test_read_field_types(self): - print('Starting field types test...') - # Set up header - header = RecordHeader() - - # Test U1 (unsigned 1-byte integer) - test_data = bytes([42]) - self.write_to_stream(test_data) - header.len = 1 - value = self.parser.readField(header, "U1") - self.assertEqual(value, 42) - - # Test U2 (unsigned 2-byte integer) - self.test_stream.seek(0) - self.test_stream.truncate() - test_data = bytes([0x2A, 0x00]) - self.write_to_stream(test_data) - header.len = 2 - value = self.parser.readField(header, "U2") - self.assertEqual(value, 42) - - # Test I1 (signed 1-byte integer) - self.test_stream.seek(0) - self.test_stream.truncate() - test_data = bytes([0xFF]) # -1 in two's complement - self.write_to_stream(test_data) - header.len = 1 - value = self.parser.readField(header, "I1") - self.assertEqual(value, -1) - - def test_read_string(self): - print('Starting string test...') - # Set up header - header = RecordHeader() - header.len = 6 # 1 byte length + 5 bytes string - - # Test Cn (variable-length string) - test_str = b"Hello" - test_data = bytes([len(test_str)]) + test_str # String length + string data - self.write_to_stream(test_data) - value = self.parser.readCn(header) - self.assertEqual(value, "Hello") - - # Test empty string - self.test_stream.seek(0) - self.test_stream.truncate() - test_data = bytes([0]) # Length 0 - self.write_to_stream(test_data) - header.len = 1 - value = self.parser.readCn(header) - self.assertEqual(value, "") - - def test_read_array(self): - print('Starting array test...') - # Test array of U1 - test_data = bytes([10, 20, 30]) - self.write_to_stream(test_data) - header = RecordHeader() - header.len = 3 - values = self.parser.readArray(header, 3, "U1") - self.assertEqual(values, [10, 20, 30]) - - def test_append_field_parser(self): - print('Starting append field parser test...') - def base_parser(*args): - return [1, 2] - - def field_action(*args): - return 3 - - new_parser = appendFieldParser(base_parser, field_action) - result = new_parser() - self.assertEqual(result, [1, 2, 3]) - - def test_end_of_record(self): - print('Starting end of record test...') - # Test handling of premature end of record - test_data = bytes([0x02]) # Only 1 byte when 2 are expected - self.write_to_stream(test_data) - header = RecordHeader() - header.len = 2 - with self.assertRaises(EndOfRecordException): - self.parser.readField(header, "U2") - - def test_eof(self): - print('Starting EOF test...') - # Test handling of EOF - self.write_to_stream(bytes([])) # Empty stream - header = RecordHeader() - header.len = 1 - with self.assertRaises(EofException): - self.parser.readField(header, "U1") - -if __name__ == '__main__': - unittest.main()