72 Commits

Author SHA1 Message Date
c7890b4a8e [package] doc string cleanup extravaganza (#59843)
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/59843

Test Plan: Imported from OSS

Reviewed By: SplitInfinity

Differential Revision: D29049342

Pulled By: Lilyjjo

fbshipit-source-id: 3330fb439f28dda0cafef5797ff61311f4afbf76
2021-06-10 21:21:48 -07:00
935057fc74 [package] turn MockZipReader into DirectoryReader and add test coverage (#59107)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/59107

Adding documentation, test coverage, and a missing method to the `DirectoryReader` class. `DirectoryReader` was previously named `MockZipReader`, and is used for operating on opened package archives via a `PackageImporter`.

Test Plan: Imported from OSS

Reviewed By: SplitInfinity

Differential Revision: D28760410

Pulled By: Lilyjjo

fbshipit-source-id: aa9d0a68e19738a6d5555bb04ce33af6a53f1268
2021-06-08 08:02:34 -07:00
dceaf98e79 [torch][package] Fix importlib.resources.path for python <3.8.8 (#58718)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/58718

`PackageImporter` does not populate `module.__spec__.origin`, which causes an
unhandled `Exception` to be raised when using `importlib.resources.path` to get
a path to a binary file resource in the package in python <3.8.6.

This commit fixes this issue by setting `module.__spec__.origin` to
"<package_importer>". The actual value is not important as far as I can tell;
the simple fact that it is not `None` allows `importlib` to avoid raising an
`Exception` in `importlib.resources.path`.

Test Plan:
This commit adds a unit test to `test_resources.py` that tests that
`importlib.resources.path` can be used within a package.

Reviewed By: suo

Differential Revision: D28589117

fbshipit-source-id: 870d606a30fce6884ae48b03ff71c0864e4b325f
2021-05-21 19:16:54 -07:00
ed4cda0183 [pkg] opt into autoformat
Summary: woooo

Test Plan: arc lint --apply-patches --take BLACK --paths-cmd 'hg files -I "caffe2/**/*.py"'

Reviewed By: SplitInfinity

Differential Revision: D28608934

fbshipit-source-id: 7768fed50a87883a95319376c0a6d73a9492bdcc
2021-05-21 15:03:52 -07:00
7dd08504f6 [package] fix persistent_load error (#58439)
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/58439

Test Plan: Imported from OSS

Reviewed By: suo

Differential Revision: D28494250

Pulled By: Lilyjjo

fbshipit-source-id: c068760db9c25dcbf5a88ea9343eab11f0e7736a
2021-05-17 17:38:53 -07:00
9403fe17ce [torch.package/TorchScript] logic to enable sharing of tensors on load (#57573)
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/57573

Test Plan: Imported from OSS

Reviewed By: suo

Differential Revision: D28226975

Pulled By: Lilyjjo

fbshipit-source-id: bc8cb3e8052fa18336c437e0601d8b0028fd1895
2021-05-14 08:21:43 -07:00
307375a88e [torch.Package/TorchScript] torch.Package python logic to save TorchScript (#54893)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/54893

Adds logic to torch.Package's `PackageExporter` and `PackageImporter` to handle TorchScript objects. Also adds necessary `__reduce_package__` methods to `ScriptModule` and `RecursiveScriptModule` to enable this

API:
```
# create scripted objects
scripted_mod = torch.jit.script(Mod1("initial_1"))
scripted_mod2 = torch.jit.script(Mod2("initial_2"))

# save objects into package
with PackageExporter(filename, verbose=False) as e:
            e.save_pickle("res", "mod.pkl", scripted_mod)
            e.save_pickle("res", "mod2.pkl", scripted_mod2)

# load scripted objects from package
importer = PackageImporter(filename)
scripted_mod_loaded = importer.load_pickle("res", "mod.pkl")
scripted_mod2_loaded = importer.load_pickle("res", "mod2.pkl")
```

Test Plan: Imported from OSS

Reviewed By: suo

Differential Revision: D27832547

Pulled By: Lilyjjo

fbshipit-source-id: 73bf254c311fee2a2b21a9a7861d6cdc53709bd1
2021-05-14 08:21:41 -07:00
cb234e606d [package] fix corner case in PacakgeImporter.whichmodule (#57651)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/57651

We've gone back and forth on whether to emulate the `sys.modules` lookup
behavior in our own `whichmodule`, the provided test is a concrete case
for doing so.

An additional minor cleanup is to make the type of `self.modules` in
importers `Dict[str, ModuleType]`. Modules could only be None in the
dictionary in older versions of the import system

Test Plan: Imported from OSS

Reviewed By: SplitInfinity

Differential Revision: D28226536

Pulled By: suo

fbshipit-source-id: c2e6da91651ddaa4fbf7171555df9e5cbe1060fd
2021-05-06 14:15:21 -07:00
31e59c3869 torch.package change Folder to Directory and add doc strings (#56925)
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/56925

Test Plan: Imported from OSS

Reviewed By: suo

Differential Revision: D28002145

Pulled By: Lilyjjo

fbshipit-source-id: 6265970202d1530c4fb7ea10011b0e09094037d5
2021-04-28 13:03:12 -07:00
c244d1c540 [package] resolve __import__ calls on export (#55153)
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/55153

Test Plan: Imported from OSS

Reviewed By: suo

Differential Revision: D27504536

Pulled By: Lilyjjo

fbshipit-source-id: 5e3e10f213c6e0cf1755d18eb19727515362f91a
2021-04-21 15:43:15 -07:00
75024e228c Add lint for unqualified type: ignore (#56290)
Summary:
The other half of https://github.com/pytorch/pytorch/issues/56272.

Pull Request resolved: https://github.com/pytorch/pytorch/pull/56290

Test Plan:
CI should pass on the tip of this PR, and we know that the lint works because the following CI runs (before this PR was finished) failed:

- https://github.com/pytorch/pytorch/runs/2384511062
- https://github.com/pytorch/pytorch/actions/runs/765036024

Reviewed By: seemethere

Differential Revision: D27867219

Pulled By: samestep

fbshipit-source-id: e648f07b6822867e70833e23ddafe7fb7eaca235
2021-04-21 08:07:23 -07:00
8d4e6c9570 [package] make GlobGroup a public concept (#56238)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/56238

It's already functionally public due to `extern` and `mock`, but
exposing the underlying implementation makes extending PackageExporter
easier.

Changed the underscores, expose on `torch.package`, add docs, etc.

Differential Revision: D27817013

Test Plan: Imported from OSS

Reviewed By: Lilyjjo

Pulled By: suo

fbshipit-source-id: e39199e7cb5242a8bfb815777e4bb82462864027
2021-04-16 13:31:48 -07:00
fc6985eceb [package] Minor fixes to PackageExporter docstrings (#55817)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/55817

**Summary**
This commit makes minor edits to the docstrings of `PackageExporter` so
that they render properly in the `torch.package` API reference.

**Test Plan**
Continuous integration (especially the docs tests).

Test Plan: Imported from OSS

Reviewed By: gmagogsfm

Differential Revision: D27726817

Pulled By: SplitInfinity

fbshipit-source-id: b81276d7278f586fceded83d23cb4d0532f7c629
2021-04-13 10:00:38 -07:00
a84c92b78b [package] populate a special attribute on imported modules (#55255)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/55255

This allows packaged code to detect whether or not they are used in a
packaged context, and do different things depending on that. An example
where this might be useful is to control dynamic dependency loading
depending on whether or not something is packaged.

Test Plan: Imported from OSS

Reviewed By: Lilyjjo

Differential Revision: D27544245

Pulled By: suo

fbshipit-source-id: 55d44ef57281524b8d9ab890bd387de97f20bd9f
2021-04-03 00:58:59 -07:00
8c2c9450cc [package] autoformat (#53783)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/53783

Use isort + black on torch/package/

Test Plan: Imported from OSS

Reviewed By: SplitInfinity

Differential Revision: D26969020

Pulled By: suo

fbshipit-source-id: e2c0738e79bf41b6342355eb7025998178c35dc9
2021-03-15 17:18:43 -07:00
17bc70e6f7 [package] make importer a little more obscure (#51676)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/51676

We offer the ability to access the importer from within packaged modules by doing
`import resources`. This behavior is nice (and more powerful than the
importlib resources API), but I think `resources` is too common a name
(pip has a package for it)

Change to `import torch_package_importer` but open to bikeshedding

Test Plan: Imported from OSS

Reviewed By: jamesr66a

Differential Revision: D26620314

Pulled By: suo

fbshipit-source-id: 0942c99f02c0f55f5f3a1b2566961018b796bdd4
2021-03-10 12:13:15 -08:00
b4d8f4af82 [package] implement get_resource_reader API (#51674)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/51674

See
https://docs.python.org/3/library/importlib.html#importlib.abc.ResourceReader

Test Plan: Imported from OSS

Reviewed By: zdevito

Differential Revision: D26237034

Pulled By: suo

fbshipit-source-id: 4c19f6172d16b710737528d3de48372873b9368d
2021-03-10 12:11:11 -08:00
83a93ee145 [package] Pull out _UnpicklerWrapper into PackageUnpickler (#53049)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/53049

This makes our API symmetric--now we have an `Importer` aware Pickler
and Unpickler implementation that have similar interfaces.

Test Plan: Imported from OSS

Reviewed By: Lilyjjo

Differential Revision: D26734593

Pulled By: suo

fbshipit-source-id: 3479437cf6b98e0d6a8aa4907c75f0c61d5495d4
2021-03-01 18:40:52 -08:00
958d9a8364 [fx/package] make GraphModules packageable (#51976)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/51976

FX serializes things by serializing Python code as a string and exec'ing
it on load. This accomplishes one goal (we don't have to pickle the
graph object directly) but breaks the pickle abstraction in ways that
are not composable with `torch.package`.

In particular:
1. `forward` is serialized by saving Python code. On load, it's
installed
by  `exec`ing that code. This `exec` call needs to have the right
importer installed, otherwise it will not import modules from the
`torch.package` but instead import from the Python environment.
2. Any types/functions used are emitted as `import` statement in the
generated Python code. These are effectively dynamic dependencies of the
`GraphModule` being saved, and need to be registered as such so that the
`PackageImporter` will package them.

To address these, this PR introduces a new protocol for the
importer/exporter: `__reduce_package__`.

A class can implement `__reduce_package__` to customize how it is placed
in the importer/exproter. It functions very similarly to `__reduce__`,
except:
- `__reduce_package__` takes one argument, which is the
`PackageExporter`
instance. Users can use this instance to save stuff to the package to
implement their serialization. `__reduce__` takes no args.
- Only the 2-element tuple version of the return value for `__reduce__`
is supported (this could be extended if necessary).
- When the reduction function is called on load, an additional argument
is added to the beginning of the args tuple. This is the
`PackageImporter`
instance doing the loading.

The `__reduce_package__` protocol is defined using `persistent_id` and
`persistent_load`, which ensures that we can still use the cpickle
implementation of the pickler by default.

Pull Request resolved: #51971

Test Plan: Imported from OSS

Reviewed By: zdevito

Differential Revision: D26340591

Pulled By: suo

fbshipit-source-id: 5872a7d22e832056399a7372bae8a57807717882
2021-02-23 22:43:00 -08:00
0bc57f47f0 torch.Package zipfile debugging printer (#52176)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/52176

Added tooling to print out zipfile structure for PackageExporter and PackageImporter.

API looks like:
```
exporter.print_file_structure("sss" /*only include files with this in the path*/)
importer3.print_file_structure(False /*don't print storage*/, "sss" /*only include files with this in the path*/)
```

The output looks like this with the storage hidden by default:
```
─── resnet.zip
    ├── .data
    │   ├── extern_modules
    │   └── version
    ├── models
    │   └── models1.pkl
    └── torchvision
        └── models
            ├── resnet.py
            └── utils.py
```
The output looks like this with the storage being printed out:
```
─── resnet_added_attr_test.zip
    ├── .data
    │   ├── 94574437434544.storage
    │   ├── 94574468343696.storage
    │   ├── 94574470147744.storage
    │   ├── 94574470198784.storage
    │   ├── 94574470267968.storage
    │   ├── 94574474917984.storage
    │   ├── extern_modules
    │   └── version
    ├── models
    │   └── models1.pkl
    └── torchvision
        └── models
            ├── resnet.py
            └── utils.py
```

If the output is filtered with the string 'utils' it'd looks like this:
```
─── resnet_added_attr_test.zip
    └── torchvision
        └── models
            └── utils.py
```

Test Plan: Imported from OSS

Reviewed By: suo

Differential Revision: D26429795

Pulled By: Lilyjjo

fbshipit-source-id: 4fa25b0426912f939c7b52cedd6e217672891f21
2021-02-22 15:04:56 -08:00
d5ac929b62 [package] Introduce Importer to manage module namespace collisions. (#51975)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/51975

See comments in code.

Test Plan: Imported from OSS

Reviewed By: zdevito

Differential Revision: D26340592

Pulled By: suo

fbshipit-source-id: 61b16bafad15e19060710ad2d8487c776d672847
2021-02-19 10:06:04 -08:00
76e8324370 [package] rename ex/importer.py to package_ex/importer.py (#52320)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/52320

as title

Test Plan: Imported from OSS

Reviewed By: zdevito

Differential Revision: D26468416

Pulled By: suo

fbshipit-source-id: 890eecea76426918daff900402fbcbc149e48535
2021-02-19 10:04:14 -08:00