├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .pylintrc ├── .readthedocs.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.rst ├── adafruit_extended_bus.py ├── docs ├── _static │ └── favicon.ico ├── api.rst ├── conf.py ├── examples.rst └── index.rst ├── examples ├── extended_bus_simpletest.py └── extended_bus_spi_test.py ├── requirements.txt └── setup.py /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build CI 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Dump GitHub context 10 | env: 11 | GITHUB_CONTEXT: ${{ toJson(github) }} 12 | run: echo "$GITHUB_CONTEXT" 13 | - name: Translate Repo Name For Build Tools filename_prefix 14 | id: repo-name 15 | run: | 16 | echo "repo-name=adafruit-extended-bus" >> $GITHUB_OUTPUT 17 | - name: Set up Python 3.7 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: 3.7 21 | - name: Versions 22 | run: | 23 | python3 --version 24 | - name: Checkout Current Repo 25 | uses: actions/checkout@v3 26 | with: 27 | submodules: true 28 | - name: Checkout tools repo 29 | uses: actions/checkout@v3 30 | with: 31 | repository: adafruit/actions-ci-circuitpython-libs 32 | path: actions-ci 33 | - name: Install dependencies 34 | # (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.) 35 | run: | 36 | source actions-ci/install.sh 37 | - name: Pip install pylint, black, & Sphinx 38 | run: | 39 | pip install --force-reinstall pylint black Sphinx sphinx-rtd-theme 40 | - name: Library version 41 | run: git describe --dirty --always --tags 42 | - name: Check formatting 43 | run: | 44 | black --check --target-version=py35 . 45 | - name: PyLint 46 | run: | 47 | pylint $( find . -path './adafruit*.py' ) 48 | ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" )) 49 | - name: Build docs 50 | working-directory: docs 51 | run: sphinx-build -E -W -b html . _build/html 52 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Actions 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | upload-pypi: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Check For setup.py 13 | id: need-pypi 14 | run: | 15 | echo "setup-py=$( find . -wholename './setup.py' )" >> $GITHUB_OUTPUT" 16 | - name: Set up Python 17 | if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: '3.x' 21 | - name: Install dependencies 22 | if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install setuptools wheel twine 26 | - name: Build and publish 27 | if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') 28 | env: 29 | TWINE_USERNAME: ${{ secrets.pypi_username }} 30 | TWINE_PASSWORD: ${{ secrets.pypi_password }} 31 | run: | 32 | python setup.py sdist 33 | twine upload dist/* 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.mpy 2 | .idea 3 | __pycache__ 4 | _build 5 | *.pyc 6 | .env 7 | .python-version 8 | build*/ 9 | bundles 10 | *.DS_Store 11 | .eggs 12 | dist 13 | **/*.egg-info 14 | .vscode 15 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | 3 | # A comma-separated list of package or module names from where C extensions may 4 | # be loaded. Extensions are loading into the active Python interpreter and may 5 | # run arbitrary code 6 | extension-pkg-whitelist= 7 | 8 | # Add files or directories to the blacklist. They should be base names, not 9 | # paths. 10 | ignore=CVS 11 | 12 | # Add files or directories matching the regex patterns to the blacklist. The 13 | # regex matches against base names, not paths. 14 | ignore-patterns= 15 | 16 | # Python code to execute, usually for sys.path manipulation such as 17 | # pygtk.require(). 18 | #init-hook= 19 | 20 | # Use multiple processes to speed up Pylint. 21 | # jobs=1 22 | jobs=2 23 | 24 | # List of plugins (as comma separated values of python modules names) to load, 25 | # usually to register additional checkers. 26 | load-plugins= 27 | 28 | # Pickle collected data for later comparisons. 29 | persistent=yes 30 | 31 | # Specify a configuration file. 32 | #rcfile= 33 | 34 | # Allow loading of arbitrary C extensions. Extensions are imported into the 35 | # active Python interpreter and may run arbitrary code. 36 | unsafe-load-any-extension=no 37 | 38 | 39 | [MESSAGES CONTROL] 40 | 41 | # Only show warnings with the listed confidence levels. Leave empty to show 42 | # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED 43 | confidence= 44 | 45 | # Disable the message, report, category or checker with the given id(s). You 46 | # can either give multiple identifiers separated by comma (,) or put this 47 | # option multiple times (only on the command line, not in the configuration 48 | # file where it should appear only once).You can also use "--disable=all" to 49 | # disable everything first and then reenable specific checks. For example, if 50 | # you want to run only the similarities checker, you can use "--disable=all 51 | # --enable=similarities". If you want to run only the classes checker, but have 52 | # no Warning level messages displayed, use"--disable=all --enable=classes 53 | # --disable=W" 54 | # disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call 55 | disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation 56 | 57 | # Enable the message, report, category or checker with the given id(s). You can 58 | # either give multiple identifier separated by comma (,) or put this option 59 | # multiple time (only on the command line, not in the configuration file where 60 | # it should appear only once). See also the "--disable" option for examples. 61 | enable= 62 | 63 | 64 | [REPORTS] 65 | 66 | # Python expression which should return a note less than 10 (10 is the highest 67 | # note). You have access to the variables errors warning, statement which 68 | # respectively contain the number of errors / warnings messages and the total 69 | # number of statements analyzed. This is used by the global evaluation report 70 | # (RP0004). 71 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 72 | 73 | # Template used to display messages. This is a python new-style format string 74 | # used to format the message information. See doc for all details 75 | #msg-template= 76 | 77 | # Set the output format. Available formats are text, parseable, colorized, json 78 | # and msvs (visual studio).You can also give a reporter class, eg 79 | # mypackage.mymodule.MyReporterClass. 80 | output-format=text 81 | 82 | # Tells whether to display a full report or only the messages 83 | reports=no 84 | 85 | # Activate the evaluation score. 86 | score=yes 87 | 88 | 89 | [REFACTORING] 90 | 91 | # Maximum number of nested blocks for function / method body 92 | max-nested-blocks=5 93 | 94 | 95 | [LOGGING] 96 | 97 | # Logging modules to check that the string format arguments are in logging 98 | # function parameter format 99 | logging-modules=logging 100 | 101 | 102 | [SPELLING] 103 | 104 | # Spelling dictionary name. Available dictionaries: none. To make it working 105 | # install python-enchant package. 106 | spelling-dict= 107 | 108 | # List of comma separated words that should not be checked. 109 | spelling-ignore-words= 110 | 111 | # A path to a file that contains private dictionary; one word per line. 112 | spelling-private-dict-file= 113 | 114 | # Tells whether to store unknown words to indicated private dictionary in 115 | # --spelling-private-dict-file option instead of raising a message. 116 | spelling-store-unknown-words=no 117 | 118 | 119 | [MISCELLANEOUS] 120 | 121 | # List of note tags to take in consideration, separated by a comma. 122 | # notes=FIXME,XXX,TODO 123 | notes=FIXME,XXX 124 | 125 | 126 | [TYPECHECK] 127 | 128 | # List of decorators that produce context managers, such as 129 | # contextlib.contextmanager. Add to this list to register other decorators that 130 | # produce valid context managers. 131 | contextmanager-decorators=contextlib.contextmanager 132 | 133 | # List of members which are set dynamically and missed by pylint inference 134 | # system, and so shouldn't trigger E1101 when accessed. Python regular 135 | # expressions are accepted. 136 | generated-members= 137 | 138 | # Tells whether missing members accessed in mixin class should be ignored. A 139 | # mixin class is detected if its name ends with "mixin" (case insensitive). 140 | ignore-mixin-members=yes 141 | 142 | # This flag controls whether pylint should warn about no-member and similar 143 | # checks whenever an opaque object is returned when inferring. The inference 144 | # can return multiple potential results while evaluating a Python object, but 145 | # some branches might not be evaluated, which results in partial inference. In 146 | # that case, it might be useful to still emit no-member and other checks for 147 | # the rest of the inferred objects. 148 | ignore-on-opaque-inference=yes 149 | 150 | # List of class names for which member attributes should not be checked (useful 151 | # for classes with dynamically set attributes). This supports the use of 152 | # qualified names. 153 | ignored-classes=optparse.Values,thread._local,_thread._local 154 | 155 | # List of module names for which member attributes should not be checked 156 | # (useful for modules/projects where namespaces are manipulated during runtime 157 | # and thus existing member attributes cannot be deduced by static analysis. It 158 | # supports qualified module names, as well as Unix pattern matching. 159 | ignored-modules=board 160 | 161 | # Show a hint with possible names when a member name was not found. The aspect 162 | # of finding the hint is based on edit distance. 163 | missing-member-hint=yes 164 | 165 | # The minimum edit distance a name should have in order to be considered a 166 | # similar match for a missing member name. 167 | missing-member-hint-distance=1 168 | 169 | # The total number of similar names that should be taken in consideration when 170 | # showing a hint for a missing member. 171 | missing-member-max-choices=1 172 | 173 | 174 | [VARIABLES] 175 | 176 | # List of additional names supposed to be defined in builtins. Remember that 177 | # you should avoid to define new builtins when possible. 178 | additional-builtins= 179 | 180 | # Tells whether unused global variables should be treated as a violation. 181 | allow-global-unused-variables=yes 182 | 183 | # List of strings which can identify a callback function by name. A callback 184 | # name must start or end with one of those strings. 185 | callbacks=cb_,_cb 186 | 187 | # A regular expression matching the name of dummy variables (i.e. expectedly 188 | # not used). 189 | dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ 190 | 191 | # Argument names that match this expression will be ignored. Default to name 192 | # with leading underscore 193 | ignored-argument-names=_.*|^ignored_|^unused_ 194 | 195 | # Tells whether we should check for unused import in __init__ files. 196 | init-import=no 197 | 198 | # List of qualified module names which can have objects that can redefine 199 | # builtins. 200 | redefining-builtins-modules=six.moves,future.builtins 201 | 202 | 203 | [FORMAT] 204 | 205 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. 206 | # expected-line-ending-format= 207 | expected-line-ending-format=LF 208 | 209 | # Regexp for a line that is allowed to be longer than the limit. 210 | ignore-long-lines=^\s*(# )??$ 211 | 212 | # Number of spaces of indent required inside a hanging or continued line. 213 | indent-after-paren=4 214 | 215 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 216 | # tab). 217 | indent-string=' ' 218 | 219 | # Maximum number of characters on a single line. 220 | max-line-length=100 221 | 222 | # Maximum number of lines in a module 223 | max-module-lines=1000 224 | 225 | # List of optional constructs for which whitespace checking is disabled. `dict- 226 | # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. 227 | # `trailing-comma` allows a space between comma and closing bracket: (a, ). 228 | # `empty-line` allows space-only lines. 229 | no-space-check=trailing-comma,dict-separator 230 | 231 | # Allow the body of a class to be on the same line as the declaration if body 232 | # contains single statement. 233 | single-line-class-stmt=no 234 | 235 | # Allow the body of an if to be on the same line as the test if there is no 236 | # else. 237 | single-line-if-stmt=no 238 | 239 | 240 | [SIMILARITIES] 241 | 242 | # Ignore comments when computing similarities. 243 | ignore-comments=yes 244 | 245 | # Ignore docstrings when computing similarities. 246 | ignore-docstrings=yes 247 | 248 | # Ignore imports when computing similarities. 249 | ignore-imports=no 250 | 251 | # Minimum lines number of a similarity. 252 | min-similarity-lines=4 253 | 254 | 255 | [BASIC] 256 | 257 | # Naming hint for argument names 258 | argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 259 | 260 | # Regular expression matching correct argument names 261 | argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 262 | 263 | # Naming hint for attribute names 264 | attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 265 | 266 | # Regular expression matching correct attribute names 267 | attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 268 | 269 | # Bad variable names which should always be refused, separated by a comma 270 | bad-names=foo,bar,baz,toto,tutu,tata 271 | 272 | # Naming hint for class attribute names 273 | class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 274 | 275 | # Regular expression matching correct class attribute names 276 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 277 | 278 | # Naming hint for class names 279 | # class-name-hint=[A-Z_][a-zA-Z0-9]+$ 280 | class-name-hint=[A-Z_][a-zA-Z0-9_]+$ 281 | 282 | # Regular expression matching correct class names 283 | # class-rgx=[A-Z_][a-zA-Z0-9]+$ 284 | class-rgx=[A-Z_][a-zA-Z0-9_]+$ 285 | 286 | # Naming hint for constant names 287 | const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 288 | 289 | # Regular expression matching correct constant names 290 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 291 | 292 | # Minimum line length for functions/classes that require docstrings, shorter 293 | # ones are exempt. 294 | docstring-min-length=-1 295 | 296 | # Naming hint for function names 297 | function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 298 | 299 | # Regular expression matching correct function names 300 | function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 301 | 302 | # Good variable names which should always be accepted, separated by a comma 303 | # good-names=i,j,k,ex,Run,_ 304 | good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ 305 | 306 | # Include a hint for the correct naming format with invalid-name 307 | include-naming-hint=no 308 | 309 | # Naming hint for inline iteration names 310 | inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ 311 | 312 | # Regular expression matching correct inline iteration names 313 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ 314 | 315 | # Naming hint for method names 316 | method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 317 | 318 | # Regular expression matching correct method names 319 | method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 320 | 321 | # Naming hint for module names 322 | module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 323 | 324 | # Regular expression matching correct module names 325 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 326 | 327 | # Colon-delimited sets of names that determine each other's naming style when 328 | # the name regexes allow several styles. 329 | name-group= 330 | 331 | # Regular expression which should only match function or class names that do 332 | # not require a docstring. 333 | no-docstring-rgx=^_ 334 | 335 | # List of decorators that produce properties, such as abc.abstractproperty. Add 336 | # to this list to register other decorators that produce valid properties. 337 | property-classes=abc.abstractproperty 338 | 339 | # Naming hint for variable names 340 | variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 341 | 342 | # Regular expression matching correct variable names 343 | variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 344 | 345 | 346 | [IMPORTS] 347 | 348 | # Allow wildcard imports from modules that define __all__. 349 | allow-wildcard-with-all=no 350 | 351 | # Analyse import fallback blocks. This can be used to support both Python 2 and 352 | # 3 compatible code, which means that the block might have code that exists 353 | # only in one or another interpreter, leading to false positives when analysed. 354 | analyse-fallback-blocks=no 355 | 356 | # Deprecated modules which should not be used, separated by a comma 357 | deprecated-modules=optparse,tkinter.tix 358 | 359 | # Create a graph of external dependencies in the given file (report RP0402 must 360 | # not be disabled) 361 | ext-import-graph= 362 | 363 | # Create a graph of every (i.e. internal and external) dependencies in the 364 | # given file (report RP0402 must not be disabled) 365 | import-graph= 366 | 367 | # Create a graph of internal dependencies in the given file (report RP0402 must 368 | # not be disabled) 369 | int-import-graph= 370 | 371 | # Force import order to recognize a module as part of the standard 372 | # compatibility libraries. 373 | known-standard-library= 374 | 375 | # Force import order to recognize a module as part of a third party library. 376 | known-third-party=enchant 377 | 378 | 379 | [CLASSES] 380 | 381 | # List of method names used to declare (i.e. assign) instance attributes. 382 | defining-attr-methods=__init__,__new__,setUp 383 | 384 | # List of member names, which should be excluded from the protected access 385 | # warning. 386 | exclude-protected=_asdict,_fields,_replace,_source,_make 387 | 388 | # List of valid names for the first argument in a class method. 389 | valid-classmethod-first-arg=cls 390 | 391 | # List of valid names for the first argument in a metaclass class method. 392 | valid-metaclass-classmethod-first-arg=mcs 393 | 394 | 395 | [DESIGN] 396 | 397 | # Maximum number of arguments for function / method 398 | max-args=5 399 | 400 | # Maximum number of attributes for a class (see R0902). 401 | # max-attributes=7 402 | max-attributes=11 403 | 404 | # Maximum number of boolean expressions in a if statement 405 | max-bool-expr=5 406 | 407 | # Maximum number of branch for function / method body 408 | max-branches=12 409 | 410 | # Maximum number of locals for function / method body 411 | max-locals=15 412 | 413 | # Maximum number of parents for a class (see R0901). 414 | max-parents=7 415 | 416 | # Maximum number of public methods for a class (see R0904). 417 | max-public-methods=20 418 | 419 | # Maximum number of return / yield for function / method body 420 | max-returns=6 421 | 422 | # Maximum number of statements in function / method body 423 | max-statements=50 424 | 425 | # Minimum number of public methods for a class (see R0903). 426 | min-public-methods=1 427 | 428 | 429 | [EXCEPTIONS] 430 | 431 | # Exceptions that will emit a warning when being caught. Defaults to 432 | # "Exception" 433 | overgeneral-exceptions=Exception 434 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | python: 2 | version: 3 3 | requirements_file: requirements.txt 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Adafruit Community Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and leaders pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level or type of 9 | experience, education, socio-economic status, nationality, personal appearance, 10 | race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | We are committed to providing a friendly, safe and welcoming environment for 15 | all. 16 | 17 | Examples of behavior that contributes to creating a positive environment 18 | include: 19 | 20 | * Be kind and courteous to others 21 | * Using welcoming and inclusive language 22 | * Being respectful of differing viewpoints and experiences 23 | * Collaborating with other community members 24 | * Gracefully accepting constructive criticism 25 | * Focusing on what is best for the community 26 | * Showing empathy towards other community members 27 | 28 | Examples of unacceptable behavior by participants include: 29 | 30 | * The use of sexualized language or imagery and sexual attention or advances 31 | * The use of inappropriate images, including in a community member's avatar 32 | * The use of inappropriate language, including in a community member's nickname 33 | * Any spamming, flaming, baiting or other attention-stealing behavior 34 | * Excessive or unwelcome helping; answering outside the scope of the question 35 | asked 36 | * Trolling, insulting/derogatory comments, and personal or political attacks 37 | * Promoting or spreading disinformation, lies, or conspiracy theories against 38 | a person, group, organisation, project, or community 39 | * Public or private harassment 40 | * Publishing others' private information, such as a physical or electronic 41 | address, without explicit permission 42 | * Other conduct which could reasonably be considered inappropriate 43 | 44 | The goal of the standards and moderation guidelines outlined here is to build 45 | and maintain a respectful community. We ask that you don’t just aim to be 46 | "technically unimpeachable", but rather try to be your best self. 47 | 48 | We value many things beyond technical expertise, including collaboration and 49 | supporting others within our community. Providing a positive experience for 50 | other community members can have a much more significant impact than simply 51 | providing the correct answer. 52 | 53 | ## Our Responsibilities 54 | 55 | Project leaders are responsible for clarifying the standards of acceptable 56 | behavior and are expected to take appropriate and fair corrective action in 57 | response to any instances of unacceptable behavior. 58 | 59 | Project leaders have the right and responsibility to remove, edit, or 60 | reject messages, comments, commits, code, issues, and other contributions 61 | that are not aligned to this Code of Conduct, or to ban temporarily or 62 | permanently any community member for other behaviors that they deem 63 | inappropriate, threatening, offensive, or harmful. 64 | 65 | ## Moderation 66 | 67 | Instances of behaviors that violate the Adafruit Community Code of Conduct 68 | may be reported by any member of the community. Community members are 69 | encouraged to report these situations, including situations they witness 70 | involving other community members. 71 | 72 | You may report in the following ways: 73 | 74 | In any situation, you may send an email to . 75 | 76 | On the Adafruit Discord, you may send an open message from any channel 77 | to all Community Moderators by tagging @community moderators. You may 78 | also send an open message from any channel, or a direct message to 79 | @kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442, 80 | @sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175. 81 | 82 | Email and direct message reports will be kept confidential. 83 | 84 | In situations on Discord where the issue is particularly egregious, possibly 85 | illegal, requires immediate action, or violates the Discord terms of service, 86 | you should also report the message directly to Discord. 87 | 88 | These are the steps for upholding our community’s standards of conduct. 89 | 90 | 1. Any member of the community may report any situation that violates the 91 | Adafruit Community Code of Conduct. All reports will be reviewed and 92 | investigated. 93 | 2. If the behavior is an egregious violation, the community member who 94 | committed the violation may be banned immediately, without warning. 95 | 3. Otherwise, moderators will first respond to such behavior with a warning. 96 | 4. Moderators follow a soft "three strikes" policy - the community member may 97 | be given another chance, if they are receptive to the warning and change their 98 | behavior. 99 | 5. If the community member is unreceptive or unreasonable when warned by a 100 | moderator, or the warning goes unheeded, they may be banned for a first or 101 | second offense. Repeated offenses will result in the community member being 102 | banned. 103 | 104 | ## Scope 105 | 106 | This Code of Conduct and the enforcement policies listed above apply to all 107 | Adafruit Community venues. This includes but is not limited to any community 108 | spaces (both public and private), the entire Adafruit Discord server, and 109 | Adafruit GitHub repositories. Examples of Adafruit Community spaces include 110 | but are not limited to meet-ups, audio chats on the Adafruit Discord, or 111 | interaction at a conference. 112 | 113 | This Code of Conduct applies both within project spaces and in public spaces 114 | when an individual is representing the project or its community. As a community 115 | member, you are representing our community, and are expected to behave 116 | accordingly. 117 | 118 | ## Attribution 119 | 120 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 121 | version 1.4, available at 122 | , 123 | and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). 124 | 125 | For other projects adopting the Adafruit Community Code of 126 | Conduct, please contact the maintainers of those projects for enforcement. 127 | If you wish to use this code of conduct for your own project, consider 128 | explicitly mentioning your moderation policy or making a copy with your 129 | own moderation policy so as to avoid confusion. 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Melissa LeBlanc-Williams for Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | .. image:: https://readthedocs.org/projects/adafruit-python-extended_bus/badge/?version=latest 5 | :target: https://circuitpython.readthedocs.io/projects/extended_bus/en/latest/ 6 | :alt: Documentation Status 7 | 8 | .. image:: https://img.shields.io/discord/327254708534116352.svg 9 | :target: https://adafru.it/discord 10 | :alt: Discord 11 | 12 | .. image:: https://github.com/adafruit/Adafruit_Python_Extended_Bus/workflows/Build%20CI/badge.svg 13 | :target: https://github.com/adafruit/Adafruit_Python_Extended_Bus/actions 14 | :alt: Build Status 15 | 16 | .. image:: https://img.shields.io/badge/code%20style-black-000000.svg 17 | :target: https://github.com/psf/black 18 | :alt: Code Style: Black 19 | 20 | Helper Library for Blinka to allow creating I2C and SPI busio objects by passing in the Bus ID. 21 | This library is not compatible with CircuitPython and is intended to only be run on Linux devices. 22 | 23 | Dependencies 24 | ============= 25 | This driver depends on: 26 | 27 | * `Adafruit Python `_ 28 | 29 | Please ensure all dependencies are available on the Python filesystem. 30 | This is easily achieved by downloading 31 | `the Adafruit library and driver bundle `_. 32 | 33 | Installing from PyPI 34 | ===================== 35 | 36 | On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from 37 | PyPI `_. To install for current user: 38 | 39 | .. code-block:: shell 40 | 41 | pip3 install adafruit-extended-bus 42 | 43 | To install system-wide (this may be required in some cases): 44 | 45 | .. code-block:: shell 46 | 47 | sudo pip3 install adafruit-extended-bus 48 | 49 | To install in a virtual environment in your current project: 50 | 51 | .. code-block:: shell 52 | 53 | mkdir project-name && cd project-name 54 | python3 -m venv .env 55 | source .env/bin/activate 56 | pip3 install adafruit-extended-bus 57 | 58 | Usage Example 59 | ============= 60 | 61 | .. code-block:: python 62 | 63 | from adafruit_extended_bus import ExtendedI2C as I2C 64 | import adafruit_bme280 65 | 66 | # Create library object using our Extended Bus I2C port 67 | i2c = I2C(1) # Device is /dev/i2c-1 68 | bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) 69 | print("\nTemperature: %0.1f C" % bme280.temperature) 70 | 71 | Contributing 72 | ============ 73 | 74 | Contributions are welcome! Please read our `Code of Conduct 75 | `_ 76 | before contributing to help this project stay welcoming. 77 | 78 | Documentation 79 | ============= 80 | 81 | For information on building library documentation, please check out `this guide `_. 82 | -------------------------------------------------------------------------------- /adafruit_extended_bus.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) 2020 Melissa LeBlanc-Williams for Adafruit Industries 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | """ 23 | `adafruit_extended_bus` 24 | ================================================================================ 25 | 26 | Helper Library for Blinka to allow creating I2C and SPI busio objects by passing in the Bus ID. 27 | This library is not compatible with CircuitPython and is intended to only be run on Linux devices. 28 | 29 | * Author(s): Melissa LeBlanc-Williams 30 | 31 | """ 32 | 33 | # imports 34 | import threading 35 | 36 | from os import path 37 | from busio import I2C, SPI 38 | from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C 39 | from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI 40 | 41 | __version__ = "0.0.0-auto.0" 42 | __repo__ = "https://github.com/adafruit/Adafruit_Python_Extended_Bus.git" 43 | 44 | 45 | class ExtendedI2C(I2C): 46 | """Extended I2C is a busio extension that allows creating a compatible 47 | I2C object using the Bus ID number. The bus ID is the number at the end 48 | of /dev/i2c-# and you can find which I2C devices you have by typing 49 | ``ls /dev/i2c*``""" 50 | 51 | # pylint: disable=super-init-not-called 52 | def __init__(self, bus_id, frequency=400000): 53 | self.init(bus_id, frequency) 54 | 55 | # pylint: enable=super-init-not-called 56 | 57 | # pylint: disable=arguments-differ 58 | def init(self, bus_id, frequency): 59 | self.deinit() 60 | 61 | # Check if the file /dev/i2c-{bus_id} exists and error if not 62 | if not path.exists(f"/dev/i2c-{bus_id}"): 63 | raise ValueError(f"No device found for /dev/i2c-{bus_id}") 64 | # Attempt to open using _I2C 65 | self._i2c = _I2C(bus_id, mode=_I2C.MASTER, baudrate=frequency) 66 | 67 | self._lock = threading.RLock() 68 | 69 | # pylint: enable=arguments-differ 70 | 71 | 72 | # pylint: disable=too-few-public-methods 73 | class ExtendedSPI(SPI): 74 | """Extended SPI is a busio extension that allows creating a compatible 75 | SPI object using the Bus ID number. The bus ID is the numbers at the end 76 | of /dev/spidev#.# and you can find which SPI devices you have by typing 77 | ``ls /dev/spi*``""" 78 | 79 | # pylint: disable=invalid-name, redefined-builtin 80 | class Pin: 81 | """Fake Pin class""" 82 | 83 | def __init__(self, id): 84 | self.id = id 85 | 86 | # pylint: enable=invalid-name, redefined-builtin 87 | 88 | # pylint: disable=super-init-not-called 89 | def __init__(self, bus_id, chip_select): 90 | self.deinit() 91 | 92 | # Check if the file /dev/i2c-{bus_id} exists and error if not 93 | if not path.exists(f"/dev/spidev{bus_id}.{chip_select}"): 94 | raise ValueError(f"No device found for /dev/spidev{bus_id}.{chip_select}") 95 | 96 | self._spi = _SPI((bus_id, chip_select)) 97 | # Pins aren't used in Linux, so we just use fake pins 98 | self._pins = (self.Pin(0), self.Pin(0), self.Pin(0)) 99 | 100 | # pylint: enable=super-init-not-called 101 | 102 | 103 | # pylint: enable=too-few-public-methods 104 | -------------------------------------------------------------------------------- /docs/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_Python_Extended_Bus/464ea7f9ba0d7f0d5699d91ecb53770fd0700c8d/docs/_static/favicon.ico -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | 2 | .. If you created a package, create one automodule per module in the package. 3 | 4 | .. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) 5 | .. use this format as the module name: "adafruit_foo.foo" 6 | 7 | .. automodule:: adafruit_extended_bus 8 | :members: 9 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import sys 5 | 6 | sys.path.insert(0, os.path.abspath("..")) 7 | 8 | # -- General configuration ------------------------------------------------ 9 | 10 | # Add any Sphinx extension module names here, as strings. They can be 11 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 12 | # ones. 13 | extensions = [ 14 | "sphinx.ext.autodoc", 15 | "sphinx.ext.intersphinx", 16 | "sphinx.ext.napoleon", 17 | "sphinx.ext.todo", 18 | ] 19 | 20 | # Uncomment the below if you use native CircuitPython modules such as 21 | # digitalio, micropython and busio. List the modules you use. Without it, the 22 | # autodoc module docs will fail to generate with a warning. 23 | autodoc_mock_imports = ["busio"] 24 | 25 | 26 | intersphinx_mapping = { 27 | "python": ("https://docs.python.org/3.4", None), 28 | "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None), 29 | } 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | templates_path = ["_templates"] 33 | 34 | source_suffix = ".rst" 35 | 36 | # The master toctree document. 37 | master_doc = "index" 38 | 39 | # General information about the project. 40 | project = "Adafruit Extended_Bus Library" 41 | copyright = "2020 Melissa LeBlanc-Williams" 42 | author = "Melissa LeBlanc-Williams" 43 | 44 | # The version info for the project you're documenting, acts as replacement for 45 | # |version| and |release|, also used in various other places throughout the 46 | # built documents. 47 | # 48 | # The short X.Y version. 49 | version = "1.0" 50 | # The full version, including alpha/beta/rc tags. 51 | release = "1.0" 52 | 53 | # The language for content autogenerated by Sphinx. Refer to documentation 54 | # for a list of supported languages. 55 | # 56 | # This is also used if you do content translation via gettext catalogs. 57 | # Usually you set "language" from the command line for these cases. 58 | language = "en" 59 | 60 | # List of patterns, relative to source directory, that match files and 61 | # directories to ignore when looking for source files. 62 | # This patterns also effect to html_static_path and html_extra_path 63 | exclude_patterns = [ 64 | "_build", 65 | "Thumbs.db", 66 | ".DS_Store", 67 | ".env", 68 | "CODE_OF_CONDUCT.md", 69 | ] 70 | 71 | # The reST default role (used for this markup: `text`) to use for all 72 | # documents. 73 | # 74 | default_role = "any" 75 | 76 | # If true, '()' will be appended to :func: etc. cross-reference text. 77 | # 78 | add_function_parentheses = True 79 | 80 | # The name of the Pygments (syntax highlighting) style to use. 81 | pygments_style = "sphinx" 82 | 83 | # If true, `todo` and `todoList` produce output, else they produce nothing. 84 | todo_include_todos = False 85 | 86 | # If this is True, todo emits a warning for each TODO entries. The default is False. 87 | todo_emit_warnings = True 88 | 89 | napoleon_numpy_docstring = False 90 | 91 | # -- Options for HTML output ---------------------------------------------- 92 | 93 | # The theme to use for HTML and HTML Help pages. See the documentation for 94 | # a list of builtin themes. 95 | # 96 | on_rtd = os.environ.get("READTHEDOCS", None) == "True" 97 | 98 | if not on_rtd: # only import and set the theme if we're building docs locally 99 | try: 100 | import sphinx_rtd_theme 101 | 102 | html_theme = "sphinx_rtd_theme" 103 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] 104 | except: 105 | html_theme = "default" 106 | html_theme_path = ["."] 107 | else: 108 | html_theme_path = ["."] 109 | 110 | # Add any paths that contain custom static files (such as style sheets) here, 111 | # relative to this directory. They are copied after the builtin static files, 112 | # so a file named "default.css" will overwrite the builtin "default.css". 113 | html_static_path = ["_static"] 114 | 115 | # The name of an image file (relative to this directory) to use as a favicon of 116 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | # 119 | html_favicon = "_static/favicon.ico" 120 | 121 | # Output file base name for HTML help builder. 122 | htmlhelp_basename = "AdafruitExtended_busLibrarydoc" 123 | 124 | # -- Options for LaTeX output --------------------------------------------- 125 | 126 | latex_elements = { 127 | # The paper size ('letterpaper' or 'a4paper'). 128 | # 'papersize': 'letterpaper', 129 | # The font size ('10pt', '11pt' or '12pt'). 130 | # 'pointsize': '10pt', 131 | # Additional stuff for the LaTeX preamble. 132 | # 'preamble': '', 133 | # Latex figure (float) alignment 134 | # 'figure_align': 'htbp', 135 | } 136 | 137 | # Grouping the document tree into LaTeX files. List of tuples 138 | # (source start file, target name, title, 139 | # author, documentclass [howto, manual, or own class]). 140 | latex_documents = [ 141 | ( 142 | master_doc, 143 | "AdafruitExtended_BusLibrary.tex", 144 | "AdafruitExtended_Bus Library Documentation", 145 | author, 146 | "manual", 147 | ), 148 | ] 149 | 150 | # -- Options for manual page output --------------------------------------- 151 | 152 | # One entry per manual page. List of tuples 153 | # (source start file, name, description, authors, manual section). 154 | man_pages = [ 155 | ( 156 | master_doc, 157 | "AdafruitExtended_Buslibrary", 158 | "Adafruit Extended_Bus Library Documentation", 159 | [author], 160 | 1, 161 | ), 162 | ] 163 | 164 | # -- Options for Texinfo output ------------------------------------------- 165 | 166 | # Grouping the document tree into Texinfo files. List of tuples 167 | # (source start file, target name, title, author, 168 | # dir menu entry, description, category) 169 | texinfo_documents = [ 170 | ( 171 | master_doc, 172 | "AdafruitExtended_BusLibrary", 173 | "Adafruit Extended_Bus Library Documentation", 174 | author, 175 | "AdafruitExtended_BusLibrary", 176 | "One line description of project.", 177 | "Miscellaneous", 178 | ), 179 | ] 180 | -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | Simple test 2 | ------------ 3 | 4 | Ensure your device works with this simple test. 5 | 6 | .. literalinclude:: ../examples/extended_bus_simpletest.py 7 | :caption: examples/extended_bus_simpletest.py 8 | :linenos: 9 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | 3 | Table of Contents 4 | ================= 5 | 6 | .. toctree:: 7 | :maxdepth: 4 8 | :hidden: 9 | 10 | self 11 | 12 | .. toctree:: 13 | :caption: Examples 14 | 15 | examples 16 | 17 | .. toctree:: 18 | :caption: API Reference 19 | :maxdepth: 3 20 | 21 | api 22 | 23 | .. toctree:: 24 | :caption: Tutorials 25 | 26 | 27 | .. toctree:: 28 | :caption: Related Products 29 | 30 | .. toctree:: 31 | :caption: Other Links 32 | 33 | Download 34 | CircuitPython Reference Documentation 35 | CircuitPython Support Forum 36 | Discord Chat 37 | Adafruit Learning System 38 | Adafruit Blog 39 | Adafruit Store 40 | 41 | Indices and tables 42 | ================== 43 | 44 | * :ref:`genindex` 45 | * :ref:`modindex` 46 | * :ref:`search` 47 | -------------------------------------------------------------------------------- /examples/extended_bus_simpletest.py: -------------------------------------------------------------------------------- 1 | """ 2 | This exmaple demonstrates how to instantiate the 3 | Adafruit BME280 Sensor using this library and just 4 | the I2C bus number. 5 | """ 6 | 7 | import adafruit_bme280 8 | from adafruit_extended_bus import ExtendedI2C as I2C 9 | 10 | # Create library object using our Extended Bus I2C port 11 | i2c = I2C(1) # Device is /dev/i2c-1 12 | bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) 13 | print(f"\nTemperature: {bme280.temperature:0.1f} C") 14 | -------------------------------------------------------------------------------- /examples/extended_bus_spi_test.py: -------------------------------------------------------------------------------- 1 | """ 2 | This exmaple demonstrates how to instantiate the 3 | Adafruit BME280 Sensor using this library and just 4 | the SPI bus and chip enable numbers. 5 | 6 | Please note that Linux will mess with the system CE pins, so 7 | we are using an alternate pin for the Chip Enable line. This 8 | library is more useful for using a SPI Device on a Bus other 9 | than 0 10 | """ 11 | 12 | import board 13 | import digitalio 14 | import adafruit_bme280 15 | from adafruit_extended_bus import ExtendedSPI as SPI 16 | 17 | # Create library object using our Extended Bus I2C port 18 | spi = SPI(1, 0) # Device is /dev/spidev1.0 19 | cs = digitalio.DigitalInOut(board.D5) 20 | bme280 = adafruit_bme280.Adafruit_BME280_SPI(spi, cs) 21 | print(f"\nTemperature: {bme280.temperature:0.1f} C") 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Adafruit-Blinka 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """A setuptools based setup module. 2 | 3 | See: 4 | https://packaging.python.org/en/latest/distributing.html 5 | https://github.com/pypa/sampleproject 6 | """ 7 | 8 | from setuptools import setup, find_packages 9 | 10 | # To use a consistent encoding 11 | from codecs import open 12 | from os import path 13 | 14 | here = path.abspath(path.dirname(__file__)) 15 | 16 | # Get the long description from the README file 17 | with open(path.join(here, "README.rst"), encoding="utf-8") as f: 18 | long_description = f.read() 19 | 20 | setup( 21 | name="adafruit-extended-bus", 22 | use_scm_version=True, 23 | setup_requires=["setuptools_scm"], 24 | description="Helper Library for Blinka to allow creating I2C and SPI busio objects by passing in the Bus ID.", 25 | long_description=long_description, 26 | long_description_content_type="text/x-rst", 27 | # The project's main homepage. 28 | url="https://github.com/adafruit/Adafruit_Python_Extended_Bus", 29 | # Author details 30 | author="Adafruit Industries", 31 | author_email="circuitpython@adafruit.com", 32 | install_requires=[ 33 | "Adafruit-Blinka", 34 | ], 35 | # Choose your license 36 | license="MIT", 37 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers 38 | classifiers=[ 39 | "Development Status :: 3 - Alpha", 40 | "Intended Audience :: Developers", 41 | "Topic :: Software Development :: Libraries", 42 | "Topic :: System :: Hardware", 43 | "License :: OSI Approved :: MIT License", 44 | "Programming Language :: Python :: 3", 45 | "Programming Language :: Python :: 3.4", 46 | "Programming Language :: Python :: 3.5", 47 | "Programming Language :: Python :: 3.7", 48 | ], 49 | # What does your project relate to? 50 | keywords="adafruit blinka circuitpython micropython extended_bus busio i2c spi extended " 51 | "bus python", 52 | # You can just specify the packages manually here if your project is 53 | # simple. Or you can use find_packages(). 54 | py_modules=["adafruit_extended_bus"], 55 | ) 56 | --------------------------------------------------------------------------------