Python supercharged for the fastai library

Overview

Welcome to fastcore

Python goodies to make your coding faster, easier, and more maintainable

Python is a powerful, dynamic language. Rather than bake everything into the language, it lets the programmer customize it to make it work for them. fastcore uses this flexibility to add to Python features inspired by other languages we've loved, like multiple dispatch from Julia, mixins from Ruby, and currying, binding, and more from Haskell. It also adds some "missing features" and clean up some rough edges in the Python standard library, such as simplifying parallel processing, and bringing ideas from NumPy over to Python's list type.

Installing

To install fastcore run: conda install fastcore (if you use Anaconda, which we strongly recommend) or pip install fastcore. For an editable install, clone this repo and run: pip install -e ".[dev]".

fastcore is tested to work on Ubuntu, Macos and Windows, for the versions tagged with the -latest suffix in these docs.

A tour

fastcore contains many features. See the docs for all the details, which cover the modules provided:

  • test: Simple testing functions
  • foundation: Mixins, delegation, composition, and more
  • xtras: Utility functions to help with functional-style programming, parallel processing, and more
  • dispatch: Multiple dispatch methods
  • transform: Pipelines of composed partially reversible transformations

Here's a (somewhat) quick tour of a few higlights, showing examples from each of these modules.

Documentation

All fast.ai projects, including this one, are built with nbdev, which is a full literate programming environment built on Jupyter Notebooks. That means that every piece of documentation, including the page you're reading now, can be accessed as interactive Jupyter notebooks. In fact, you can even grab a link directly to a notebook running interactively on Google Colab - if you want to follow along with this tour, click the link below, or click the badge at the top of the page:

colab_link('index')

Open index in Colab

The full docs are available at fastcore.fast.ai. The code in the examples and in all fast.ai libraries follow the fast.ai style guide. In order to support interactive programming, all fast.ai libraries are designed to allow for import * to be used safely, particular by ensuring that __all__ is defined in all packages. In order to see where a function is from, just type it:

coll_repr

   

   

For more details, including a link to the full documentation and source code, use doc, which pops up a window with this information:

doc(coll_repr)

The documentation also contains links to any related functions or classes, which appear like this: coll_repr (in the notebook itself you will just see a word with back-ticks around it; the links are auto-generated in the documentation site). The documentation will generally show one or more examples of use, along with any background context necessary to understand them. As you'll see, the examples for each function and method are shown as tests, rather than example outputs, so let's start by explaining that.

Testing

fastcore's testing module is designed to work well with nbdev, which is a full literate programming environment built on Jupyter Notebooks. That means that your tests, docs, and code all live together in the same notebook. fastcore and nbdev's approach to testing starts with the premise that all your tests should pass. If one fails, no more tests in a notebook are run.

Tests look like this:

test_eq(coll_repr(range(1000), 5), '(#1000) [0,1,2,3,4...]')

That's an example from the docs for coll_repr. As you see, it's not showing you the output directly. Here's what that would look like:

coll_repr(range(1000), 5)
'(#1000) [0,1,2,3,4...]'

So, the test is actually showing you what the output looks like, because if the function call didn't return '(#1000) [0,1,2,3,4...]', then the test would have failed.

So every test shown in the docs is also showing you the behavior of the library --- and vice versa!

Test functions always start with test_, and then follow with the operation being tested. So test_eq tests for equality (as you saw in the example above). This includes tests for equality of arrays and tensors, lists and generators, and many more:

test_eq([0,1,2,3], np.arange(4))

When a test fails, it prints out information about what was expected:

test_eq([0,1,2,3], np.arange(3))
----
  AssertionError: ==:
  [0, 1, 2, 3]
  [0 1 2]

If you want to check that objects are the same type, rather than the just contain the same collection, use test_eq_type.

You can test with any comparison function using test, e.g test whether an object is less than:

test(2, 3, operator.lt)

You can even test that exceptions are raised:

def divide_zero(): return 1/0
test_fail(divide_zero)

...and test that things are printed to stdout:

test_stdout(lambda: print('hi'), 'hi')

Foundations

fast.ai is unusual in that we often use mixins in our code. Mixins are widely used in many programming languages, such as Ruby, but not so much in Python. We use mixins to attach new behavior to existing libraries, or to allow modules to add new behavior to our own classes, such as in extension modules. One useful example of a mixin we define is Path.ls, which lists a directory and returns an L (an extended list class which we'll discuss shortly):

p = Path('images')
p.ls()
(#6) [Path('images/mnist3.png'),Path('images/att_00000.png'),Path('images/att_00005.png'),Path('images/att_00007.png'),Path('images/att_00006.png'),Path('images/puppy.jpg')]

You can easily add you own mixins with the patch decorator, which takes advantage of Python 3 function annotations to say what class to patch:

@patch
def num_items(self:Path): return len(self.ls())

p.num_items()
6

We also use **kwargs frequently. In python **kwargs in a parameter like means "put any additional keyword arguments into a dict called kwargs". Normally, using kwargs makes an API quite difficult to work with, because it breaks things like tab-completion and popup lists of signatures. utils provides use_kwargs and delegates to avoid this problem. See our detailed article on delegation on this topic.

GetAttr solves a similar problem (and is also discussed in the article linked above): it's allows you to use Python's exceptionally useful __getattr__ magic method, but avoids the problem that normally in Python tab-completion and docs break when using this. For instance, you can see here that Python's dir function, which is used to find the attributes of a python object, finds everything inside the self.default attribute here:

class Author:
    def __init__(self, name): self.name = name

class ProductPage(GetAttr):
    _default = 'author'
    def __init__(self,author,price,cost): self.author,self.price,self.cost = author,price,cost

p = ProductPage(Author("Jeremy"), 1.50, 0.50)
[o for o in dir(p) if not o.startswith('_')]
['author', 'cost', 'name', 'price']

Looking at that ProductPage example, it's rather verbose and duplicates a lot of attribute names, which can lead to bugs later if you change them only in one place. fastcore provides store_attr to simplify this common pattern. It also provides basic_repr to give simple objects a useful repr:

class ProductPage:
    def __init__(self,author,price,cost): store_attr()
    __repr__ = basic_repr('author,price,cost')

ProductPage("Jeremy", 1.50, 0.50)
ProductPage(author='Jeremy', price=1.5, cost=0.5)

One of the most interesting fastcore functions is the funcs_kwargs decorator. This allows class behavior to be modified without sub-classing. This can allow folks that aren't familiar with object-oriented programming to customize your class more easily. Here's an example of a class that uses funcs_kwargs:

@funcs_kwargs
class T:
    _methods=['some_method']
    def __init__(self, **kwargs): assert not kwargs, f'Passed unknown args: {kwargs}'

p = T(some_method = print)
p.some_method("hello")
hello

The assert not kwargs above is used to ensure that the user doesn't pass an unknown parameter (i.e one that's not in _methods). fastai uses funcs_kwargs in many places, for instance, you can customize any part of a DataLoader by passing your own methods.

fastcore also provides many utility functions that make a Python programmer's life easier, in fastcore.utils. We won't look at many here, since you can easily look at the docs yourself. To get you started, have a look at the docs for chunked (remember, if you're in a notebook, type doc(chunked)), which is a handy function for creating lazily generated batches from a collection.

Python's ProcessPoolExecutor is extended to allow max_workers to be set to 0, to easily turn off parallel processing. This makes it easy to debug your code in serial, then run it in parallel. It also allows you to pass arguments to your parallel function, and to ensure there's a pause between calls, in case the process you are running has race conditions. parallel makes parallel processing even easier to use, and even adds an optional progress bar.

L

Like most languages, Python allows for very concise syntax for some very common types, such as list, which can be constructed with [1,2,3]. Perl's designer Larry Wall explained the reasoning for this kind of syntax:

In metaphorical honor of Huffman’s compression code that assigns smaller numbers of bits to more common bytes. In terms of syntax, it simply means that commonly used things should be shorter, but you shouldn’t waste short sequences on less common constructs.

On this basis, fastcore has just one type that has a single letter name:L. The reason for this is that it is designed to be a replacement for list, so we want it to be just as easy to use as [1,2,3]. Here's how to create that as an L:

L(1,2,3)
(#3) [1,2,3]

The first thing to notice is that an L object includes in its representation its number of elements; that's the (#3) in the output above. If there's more than 10 elements, it will automatically truncate the list:

p = L.range(20).shuffle()
p
(#20) [0,10,7,16,5,1,14,17,9,8...]

L contains many of the same indexing ideas that NumPy's array does, including indexing with a list of indexes, or a boolean mask list:

p[2,4,6]
(#3) [7,5,14]

It also contains other methods used in array, such as L.argwhere:

p.argwhere(ge(15))
(#5) [3,7,11,14,18]

As you can see from this example, fastcore also includes a number of features that make a functional style of programming easier, such as a full range of boolean functions (e.g ge, gt, etc) which give the same answer as the functions from Python's operator module if given two parameters, but return a curried function if given one parameter.

There's too much functionality to show it all here, so be sure to check the docs. Many little things are added that we thought should have been in list in the first place, such as making this do what you'd expect (which is an error with list, but works fine with L):

1 + L(2,3,4)
(#4) [1,2,3,4]

Function dispatch and Transforms

Most Python programmers use object oriented methods and inheritance to allow different objects to behave in different ways even when called with the same method name. Some languages use a very different approach, such as Julia, which uses multiple dispatch generic functions. Python provides single dispatch generic functions as part of the standard library. fastcore provides multiple dispatch, with the typedispatch decorator (which is actually an instance of DispatchReg):

@typedispatch
def _f(x:numbers.Integral, y): return x+1
@typedispatch
def _f(x:int, y:float): return x+y

_f(3,2.0), _f(3,2)
(5.0, 4)

This approach to dispatch is particularly useful for adding implementations of functionality in extension modules or user code. It is heavily used in the Transform class. A Transform is the main building block of the fastai data pipelines. In the most general terms a transform can be any function you want to apply to your data, however the Transform class provides several mechanisms that make the process of building them easy and flexible (see the docs for information about each of these):

  • Type dispatch
  • Dispatch over tuples
  • Reversability
  • Type propagation
  • Preprocessing
  • Filtering based on the dataset type
  • Ordering
  • Appending new behavior with decorators

Transform looks for three special methods, encodes, decodes, and setups, which provide the implementation for __call__, decode, and setup respectively. For instance:

class A(Transform):
    def encodes(self, x): return x+1

A()(1)
2

For simple transforms like this, you can also use Transform as a decorator:

@Transform
def f(x): return x+1

f(1)
2

Transforms can be composed into a Pipeline:

@Transform
def g(x): return x/2

pipe = Pipeline([f,g])
pipe(3)
2.0

The power of Transform and Pipeline is best understood by seeing how they're used to create a complete data processing pipeline. This is explained in chapter 11 of the fastai book, which is available for free in Jupyter Notebook format.

Contributing

After you clone this repository, please run nbdev_install_git_hooks in your terminal. This sets up git hooks, which clean up the notebooks to remove the extraneous stuff stored in the notebooks (e.g. which cells you ran) which causes unnecessary merge conflicts.

To run the tests in parallel, launch nbdev_test_nbs or make test.

Before submitting a PR, check that the local library and notebooks match. The script nbdev_diff_nbs can let you know if there is a difference between the local library and the notebooks.

  • If you made a change to the notebooks in one of the exported cells, you can export it to the library with nbdev_build_lib or make fastcore.
  • If you made a change to the library, you can export it back to the notebooks with nbdev_update_lib.
Comments
  • adds mkdir

    adds mkdir

    Adds mkdir function as described in discord here.

    I feel like my tests might be a bit convoluted? Please feel free to suggest changes :)

    NOTE: The only file I really modified was 03_xtras.ipynb, I guess all the other files were changed by nbdev hooks?

    opened by lgvaz 16
  • Global patch on pathlib module breaks 3rd party library ruamel.yaml

    Global patch on pathlib module breaks 3rd party library ruamel.yaml

    hi - while helping @HenryDashwood to get his work on support fastai2 in BentoML(https://github.com/bentoml/BentoML/pull/596), we noticed an issue that is unique to fastai2, here are the code to reproduce the issue:

    Install fastcore and ruamel.yaml, the following code should run without any issue:

    conda_env_yaml = """
    name: bentoml-Demo
    channels:
      - defaults
    dependencies:
      - python=3.7.5
      - pip
    """
    from ruamel.yaml import YAML
    yaml = YAML()
    y = yaml.load(conda_env_yaml)
    from pathlib import Path
    yaml.dump(y, Path("/tmp/test.yml"))
    

    But after importing fastcore.utils with from fastcore.utils import * and run the code above again, the follow error occurs:

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-4-beaac7fd8e8a> in <module>
         11 y = yaml.load(conda_env_yaml)
         12 from pathlib import Path
    ---> 13 yaml.dump(y, Path("/tmp/test.yml"))
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/main.py in dump(self, data, stream, _kw, transform)
        447             if stream is None:
        448                 raise TypeError('Need a stream argument when not dumping from context manager')
    --> 449             return self.dump_all([data], stream, _kw, transform=transform)
        450
        451     def dump_all(self, documents, stream, _kw=enforce, transform=None):
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/main.py in dump_all(self, documents, stream, _kw, transform)
        461         self._context_manager = YAMLContextManager(self, transform=transform)
        462         for data in documents:
    --> 463             self._context_manager.dump(data)
        464         self._context_manager.teardown_output()
        465         self._output = None
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/main.py in dump(self, data)
        813             self.init_output(data)
        814         try:
    --> 815             self._yaml.representer.represent(data)
        816         except AttributeError:
        817             # nprint(dir(dumper._representer))
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/representer.py in represent(self, data)
         84         # type: (Any) -> None
         85         node = self.represent_data(data)
    ---> 86         self.serializer.serialize(node)
         87         self.represented_objects = {}
         88         self.object_keeper = []
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/serializer.py in serialize(self, node)
        115         )
        116         self.anchor_node(node)
    --> 117         self.serialize_node(node, None, None)
        118         self.emitter.emit(DocumentEndEvent(explicit=self.use_explicit_end))
        119         self.serialized_nodes = {}
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/serializer.py in serialize_node(self, node, parent, index)
        230                 )
        231                 for key, value in node.value:
    --> 232                     self.serialize_node(key, node, None)
        233                     self.serialize_node(value, node, key)
        234                 self.emitter.emit(MappingEndEvent(comment=[map_comment, end_comment]))
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/serializer.py in serialize_node(self, node, parent, index)
        178                         node.value,
        179                         style=node.style,
    --> 180                         comment=node.comment,
        181                     )
        182                 )
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in emit(self, event)
        252         while not self.need_more_events():
        253             self.event = self.events.pop(0)
    --> 254             self.state()
        255             self.event = None
        256
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in expect_first_block_mapping_key(self)
        662     def expect_first_block_mapping_key(self):
        663         # type: () -> None
    --> 664         return self.expect_block_mapping_key(first=True)
        665
        666     def expect_block_mapping_key(self, first=False):
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in expect_block_mapping_key(self, first)
        687                         pass
        688                 self.states.append(self.expect_block_mapping_simple_value)
    --> 689                 self.expect_node(mapping=True, simple_key=True)
        690                 if isinstance(self.event, AliasEvent):
        691                     self.stream.write(u' ')
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in expect_node(self, root, sequence, mapping, simple_key)
        420             if isinstance(self.event, ScalarEvent):
        421                 # nprint('@', self.indention, self.no_newline, self.column)
    --> 422                 self.expect_scalar()
        423             elif isinstance(self.event, SequenceStartEvent):
        424                 # nprint('@', self.indention, self.no_newline, self.column)
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in expect_scalar(self)
        468         # type: () -> None
        469         self.increase_indent(flow=True)
    --> 470         self.process_scalar()
        471         self.indent = self.indents.pop()
        472         self.state = self.states.pop()
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in process_scalar(self)
        883             self.write_literal(self.analysis.scalar, self.event.comment)
        884         else:
    --> 885             self.write_plain(self.analysis.scalar, split)
        886         self.analysis = None
        887         self.style = None
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/ruamel/yaml/emitter.py in write_plain(self, text, split)
       1614                         data = data.encode(self.encoding)
       1615                     try:
    -> 1616                         self.stream.write(data)
       1617                     except:  # NOQA
       1618                         sys.stdout.write(repr(data) + '\n')
    
    ~/opt/miniconda3/envs/btml-dev/lib/python3.7/site-packages/fastcore/utils.py in write(self, txt, encoding)
        428     "Write `txt` to `self`, creating directories as needed"
        429     self.parent.mkdir(parents=True,exist_ok=True)
    --> 430     with self.open('w', encoding=encoding) as f: f.write(txt)
        431
        432 # Cell
    
    TypeError: write() argument must be str, not bytes
    

    After looking into this, the reason was the following code in the fastcore/utils.py file: https://github.com/fastai/fastcore/blob/8a56bcbb2be3d5a2ab137b312c981a31d50f5cbe/fastcore/utils.py#L480

    @patch
    def write(self:Path, txt, encoding='utf8'):
        "Write `txt` to `self`, creating directories as needed"
        self.parent.mkdir(parents=True,exist_ok=True)
        with self.open('w', encoding=encoding) as f: f.write(txt)
    

    The code is adding a global patch to the pathlib.Path object, this line specifically added the method "write" to Path. However ruamel.yaml, a popular YAML handling library for python, is depending on this attribute missing, to tell if the given file path is a pathlib.Path object: https://github.com/pycontribs/ruamel-yaml/blob/7692648298f680357e09502f991ce0d1c213bfeb/main.py#L755

    This made it very hard to integrate fastai2 with BentoML for model serving, or for anything that uses ruamel.yaml. It may break other packages too. I think in general libraries should avoid this type of global patching especially on core modules like pathlib.

    opened by parano 14
  • Fix writing string as bytes in urlsave

    Fix writing string as bytes in urlsave

    The urlsave function attempts to write bytes which are loaded and decoded to string in urlread. This switches off the decoding to have bytes object to write. This issue shows up in the nbdev_new command.

    opened by jochym 8
  • Update 03_xtras: typo becuase => because

    Update 03_xtras: typo becuase => because

    Hello there, I'm enjoying reading https://fastcore.fast.ai/ documentation, and I found this one-letter typo in https://fastcore.fast.ai/xtras.html#run Thanks for your amazing work, kind regards from France. -- @Naereen

    opened by Naereen 7
  • fixes nested pipeline setup

    fixes nested pipeline setup

    Pipeline.setup was not being called in a nested pipeline situtation:

    pipe1 = Pipeline([neg])
    pipe2 = Pipeline([pipe1, neg])
    

    pipe1 was being converted to a transform by mk_transform, overriding the setup method from the pipeline.

    opened by lgvaz 7
  • Add dataclass to docments

    Add dataclass to docments

    fastcore.docments.docments can't show dataclass definition. It tryes to find this class constructor, but it is unaccessible, so it throws exception.

    from dataclasses import dataclass
    
    @dataclass
    class Person:
        name:str # The name of the person
        age:int # The age of the person
        weight:float # The weight of the person
    
    docments(Person)
    

    Output

    { 
        'age': 'The age of the person',
        'name': 'The name of the person',
        'return': None,
        'weight': 'The weight of the person'
    }
    

    The only caveat is this output would be produced if notebook already converted into script. docments of dataclass defined online in notebook couldn't return parameters' comments. cc @jph00

    enhancement 
    opened by MarkB2 6
  • Fastcore.script unable to override default arguments when importing

    Fastcore.script unable to override default arguments when importing

    Hi,

    I have recently been looking at using fastcore.script as a way to create lightweight scripts around functions which are also imported and used elsewhere. However, I seem to be experiencing some odd behaviour, which I will illustrate with a trivial example.

    Let’s say I define a script say_hello_script.py which contains:

    from fastcore.script import *
    
    
    @call_parse
    def say_hello(greeting: Param('Greeting', str) = 'Hello',
                  name: Param('Name', str) = 'World'):
        print(f'{greeting}, {name}')
    

    If I call this from the command line using python say_hello_script.py --name Chris, I get the expected output of Hello, Chris. All is good so far.

    However, now I want to call this function from a different script, so I will create a script greeter.py which contains:

    from say_hello_script import say_hello
    
    if __name__ == '__main__':
        say_hello(greeting='hi', name='person')
    

    Running python greeter.py I get the output of Hello, World, which seems to have bypassed my arguments! Is this the normal behaviour?

    Thanks, Chris

    opened by Chris-hughes10 6
  • support windows: only add lock if it runs parallelly

    support windows: only add lock if it runs parallelly

    1. support windows: 00_test and 03_xtras are not compatible with Windows
    2. Fix https://github.com/fastai/nbdev/issues/393 If the functions runs sequentially, it doesn't need a lock. And multiprocess.manager().lock() spawns one new process, notebook will be stuck on Windows.
    enhancement 
    opened by mszhanyi 6
  • Proposition: optional override to is_instance(x,t) to support both types and str in the same function

    Proposition: optional override to is_instance(x,t) to support both types and str in the same function

    splitting the is_instance, and is_instance_str seemed like a complicated solution imho, I'm not too keen with the override, but I find it much more appealing in the later uses imo.

    Then again, just a proposition.

    enhancement 
    opened by kessido 6
  • fix(FixSigMeta): remove self from signature

    fix(FixSigMeta): remove self from signature

    Remove self from signature using FixSigMeta.

    This issue came from a user reporting a log_args error on LabelSmoothingEntropy (meaning that parameters on this function were not saved).

    I noticed that the signature included self, then looked at Module which uses PrePostInitMeta, itself inheriting from FixSigMeta. Was tricky to solve but I think this should do it!

    In theory there should never be a message from log_args unless there's a signature issue.

    The only signature issues not shown are when too many parameters are passed because **kwargs is typically removed while actually everything is passed. In that case the parameter is named function.parameter (not in signature).

    opened by borisdayma 6
  • neptune-cli -> neptune-client

    neptune-cli -> neptune-client

    Not sure if neptune-cli is used anywhere, but I believe that the neptune-cli client was renamed to neptune-client.

    https://github.com/neptune-ai/neptune-client

    This should resolve the build errors I'm seeing:

    ERROR: Requested neptune-cli from https://files.pythonhosted.org/packages/ba/ae/0cdcb9d20bf3b2324d21cfd11dc05246972e9759e7609739c6ce0ef01639/neptune-cli-2.8.23-1.tar.gz#sha256=343bd3d79da2c2fd10b9cd8ffb52570f8eb91573dbf290742eefb1aa643fe2eb has different version in metadata: '2.8.23'
    Error: Process completed with exit code 1.
    
    opened by whoahbot 5
  • extend test_eq_type

    extend test_eq_type

    Change the behaviour of test_eq_type to fail if comparing tensors with different dtypes

    previously this would pass: test_eq_type(torch.zeros(10), torch.zeros(10, dtype=torch.float64))

    Now it does not

    opened by ddobrinskiy 1
  • show_doc does not display return value docment for function/method with no arguments

    show_doc does not display return value docment for function/method with no arguments

    Example from the documentation:

    class Adder:
        "An addition calculator"
        def __init__(self,
            a:int, # First operand
            b:int, # 2nd operand
        ): self.a,self.b = a,b
        
        def calculate(self
                     )->int: # Integral result of addition operator
            "Add `a` to `b`"
            return a+b
    
    show_doc(Adder.calculate)
    
    Screen Shot 2022-12-13 at 2 02 48 AM

    I would expect there to be a table entry with "Integral result of addition operator".

    opened by simonkeys 0
  • Update CONTRIBUTING.md

    Update CONTRIBUTING.md

    The most important change here is updating nbdev_install_git_hooks to nbdev_install_hooks, which I believe is necessary for compatibility with the current version of nbdev.

    opened by gsganden 0
  • Typo in `patch_to` docs

    Typo in `patch_to` docs

    The patch_to docs contain the following passage:

    Additionally you can specify that the function you want to patch should be a class attribute with as_prop = False

    @patch_to(_T5, as_prop=True)
    def add_ten(self): return self + 10
    
    t = _T5(4)
    test_eq(t.add_ten, 14)
    

    I take it that the text should say "as_prop=True" instead of "as_prop = False", so that it matches the example and the statement "you can specify that the function you want to patch should be a class attribute".

    opened by gsganden 0
Releases(1.5.27)
更新 2.0 版本,使用 Python WEB 高性能异步框架 FastAPI 制作的抖音无水印解析下载,采用前后端分离思想!

前言 这个是 2.0 版本,使用现在流行的前后端分离思想重构。 体验网址:https://douyin.bigdataboy.cn 更新日志 2020.05.30:使用 FastAPI 前后端分离重构 2020.05.02:已更新,正常使用 2020.04.27:抖音结构更新,已修复视频有水印。(失

null 64 Nov 25, 2022
📦 Autowiring dependency injection container for python 3

Lagom - Dependency injection container What Lagom is a dependency injection container designed to give you "just enough" help with building your depen

Steve B 146 Dec 29, 2022
Monitor Python applications using Spring Boot Admin

Pyctuator Monitor Python web apps using Spring Boot Admin. Pyctuator supports Flask, FastAPI, aiohttp and Tornado. Django support is planned as well.

SolarEdge Technologies 145 Dec 28, 2022
TODO aplication made with Python's FastAPI framework and Hexagonal Architecture

FastAPI Todolist Description Todolist aplication made with Python's FastAPI framework and Hexagonal Architecture. This is a test repository for the pu

Giovanni Armane 91 Dec 31, 2022
python template private service

Template for private python service This is a cookiecutter template for an internal REST API service, written in Python, inspired by layout-golang. Th

UrvanovCompany 15 Oct 2, 2022
A Python pickling decompiler and static analyzer

Fickling Fickling is a decompiler, static analyzer, and bytecode rewriter for Python pickle object serializations. Pickled Python objects are in fact

Trail of Bits 162 Dec 13, 2022
A supercharged AWS command line interface (CLI).

SAWS Motivation AWS CLI Although the AWS CLI is a great resource to manage your AWS-powered services, it's tough to remember usage of: 70+ top-level c

Donne Martin 5.1k Jan 5, 2023
A community-supported supercharged version of paperless: scan, index and archive all your physical documents

Paperless-ngx Paperless-ngx is a document management system that transforms your physical documents into a searchable online archive so you can keep,

null 5.2k Jan 4, 2023
fastgradio is a python library to quickly build and share gradio interfaces of your trained fastai models.

fastgradio is a python library to quickly build and share gradio interfaces of your trained fastai models.

Ali Abdalla 34 Jan 5, 2023
The fastai deep learning library

Welcome to fastai fastai simplifies training fast and accurate neural nets using modern best practices Important: This documentation covers fastai v2,

fast.ai 23.2k Jan 7, 2023
The fastai deep learning library

Welcome to fastai fastai simplifies training fast and accurate neural nets using modern best practices Important: This documentation covers fastai v2,

fast.ai 20.4k Feb 12, 2021
Pytorch NLP library based on FastAI

Quick NLP Quick NLP is a deep learning nlp library inspired by the fast.ai library It follows the same api as fastai and extends it allowing for quick

Agis pof 283 Nov 21, 2022
An Agnostic Computer Vision Framework - Pluggable to any Training Library: Fastai, Pytorch-Lightning with more to come

IceVision is the first agnostic computer vision framework to offer a curated collection with hundreds of high-quality pre-trained models from torchvision, MMLabs, and soon Pytorch Image Models. It orchestrates the end-to-end deep learning workflow allowing to train networks with easy-to-use robust high-performance libraries such as Pytorch-Lightning and Fastai

airctic 789 Dec 29, 2022
tsai is an open-source deep learning package built on top of Pytorch & fastai focused on state-of-the-art techniques for time series classification, regression and forecasting.

Time series Timeseries Deep Learning Pytorch fastai - State-of-the-art Deep Learning with Time Series and Sequences in Pytorch / fastai

timeseriesAI 2.8k Jan 8, 2023
pygame is a Free and Open Source python programming language library for making multimedia applications like games built on top of the excellent SDL library. C, Python, Native, OpenGL.

pygame is a Free and Open Source python programming language library for making multimedia applications like games built on top of the excellent SDL library. C, Python, Native, OpenGL.

pygame 5.6k Jan 1, 2023
Visual Automata is a Python 3 library built as a wrapper for Caleb Evans' Automata library to add more visualization features.

Visual Automata Copyright 2021 Lewi Lie Uberg Released under the MIT license Visual Automata is a Python 3 library built as a wrapper for Caleb Evans'

Lewi Uberg 55 Nov 17, 2022
A simple in-process python scheduler library, designed to be integrated seamlessly with the `datetime` standard library.

scheduler A simple in-process python scheduler library, designed to be integrated seamlessly with the datetime standard library. Due to the support of

null 30 Dec 30, 2022
A python library for face detection and features extraction based on mediapipe library

FaceAnalyzer A python library for face detection and features extraction based on mediapipe library Introduction FaceAnalyzer is a library based on me

Saifeddine ALOUI 14 Dec 30, 2022
JLC2KICAD_lib is a python script that generate a component library for KiCad from the JLCPCB/easyEDA library.

JLC2KiCad_lib is a python script that generate a component library (schematic, footprint and 3D model) for KiCad from the JLCPCB/easyEDA library. This script requires Python 3.6 or higher.

Nicolas Toussaint 73 Dec 26, 2022
Python wrappers to the C++ library SymEngine, a fast C++ symbolic manipulation library.

SymEngine Python Wrappers Python wrappers to the C++ library SymEngine, a fast C++ symbolic manipulation library. Installation Pip See License section

null 136 Dec 28, 2022